笔者从今天开始学习java多线程,从入门到放弃。今天咱们先记录java多线程的建立方式。java多线程的建立方式,能够分为四类。继承Thread类、实现Runnable接口、实现Callable接口经过FutureTask包装器来建立Thread线程、使用java提供的Executors工具获取线程池对象,从中获取线程。
一、继承Thread类建立线程
Thread自己实现了runnable接口,表明一个线程的实例。继承Thread类须要重写父类的run方法。调用自己的start方法来开启一个线程。start方法底层会调用run方法。这边我写了ExtendThread类来继承Thread类,重写run方法。这样子ExtendThread就是一个线程类了。接着在测试类中调用start开启一个线程。java
ExtendThread类多线程
开启线程
二、实现Runnable接口
实现Runnable会比继承Thread类来得更灵活,因java机制不容许类有多继承性,只容许实现多个接口。因此相对于继承Thread我仍是推荐使用这个。这边我写了ImplRunnable来实现Runnable接口。经过Thread构造函数传入Runnable实现对象进去。Thread经过静态代理方式(通俗一点讲就是代理对象包装目标对象,代理对象帮忙调用目标对象的方法,局限性很大。如今比较流行动态代理),会去调用ImplRunnable的run方法。
以下:
实现Runnable接口
并发
这里的target,就是Runnable 的实现类也就是咱们这里的ImplRunnable类函数
三、实现Callable接口经过FutureTask包装器来建立Thread线程
有时候咱们须要检测当前线程的执行状况,并根据状况对其进行中止,这时候就能够经过包装器FutureTask来解决这个问题。首先咱们建立ImplCallable类实现Callable接口传入一个返回值类型String。重写call方法,返回String类型的结果。后面经过包装器能够获取该结果工具
ImplCallable类实现了Callable接口
这里咱们来看下FutureTask包装器的结构图:FutureTask间接实现了Runnable和Future接口,能够对Runnabl进行包装。进行监测等功能扩展。性能
FutureTask包装器的结构图
调用FutureTask对Callable实现类进行包装。FutureTask可以对当前这个线程进行监测,好比futureTask.cancel取消线程任务,futureTask.get获取线程返回的结果,此结果就是刚刚咱们重写call方法里面的返回值,调用get方法线程会进入阻塞状态 。futureTask.isDone()能够判断当前线程是否执行完成。学习
4.经过线程池来建立线程。
从上面来看,咱们想要一个线程就去建立一个线程,这也实现起来很方便,但是事实上,若是并发数线程变多了,而且每一个线程执行时间比较短,这样就会频繁的去建立线程资源就会大大下降了系统的性能。一般,咱们能够用线程池来解决这个问题,首先,在服务启动的时候,咱们能够启动好几个线程,并用一个容器(如线程池)来管理这些线程。
java提供了Executors工具来给开发者建立不一样类型的线程池,这里咱们简单讲newFixedThreadPool这个方法。(后续咱们会深刻学习线程池的实现原理。)newFixedThreadPool方法建立了固定容量的线程池这里我初始化10个。测试
调用execute执行某个线程,传入Runnable的实现类。(笔者如今也是刚接触线程池不久,不可以深刻去记录一些东西。后续会不断的累计并分析给你们。)
ps:这边比较了几种建立线程的方式。线程