Callable、Future和FutureTask
无论是直接继承Thread,还是实现Runnable接口来创建线程,在执行完任务之后都无法获取执行结果。而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
Callable
Callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法call();
一般情况下Callable是配合ExecutorService来使用的,在ExecutorService接口中声明了若干个submit方法的重载版本:
示例
|
|
Future
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
在Future接口中声明了5个方法,下面依次解释每个方法的作用:
- cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
- isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
- isDone方法表示任务是否已经完成,若任务完成,则返回true;
- get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
- get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
示例
|
|
执行结果如下:
FutureTask
FutureTask类实现了RunnableFuture接口,RunnableFuture继承了Runnable接口和Future接口,所以FutureTask既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
示例
|
|
执行结果如下:
CountDownLatch、CyclicBarrier和Semaphore
CountDownLatch
CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。
示例
|
|
执行结果如下:
CyclicBarrier
通过CyclicBarrier可以实现让一组线程等待至某个状态之后再全部同时执行。CyclicBarrier类位于java.util.concurrent包下,CyclicBarrier提供2个构造器;其中:参数parties指让多少个线程或者任务等待至barrier状态;参数barrierAction为当这些线程都达到barrier状态时会执行的内容。
示例
|
|
执行结果如下:
Semaphore
Semaphore信号量可以控同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。 Semaphore类位于java.util.concurrent包下,它提供了2个构造器:
示例
一间可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。
执行结果如下:
线程间协作
线程之间的协作最经典的就是生产者-消费者模型。
使用Object的wait()和notify()实现:
|
|
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。
- Condition是个接口,基本的方法就是await()和signal()方法;
- Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition();
- 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用;
- Conditon中的await()对应Object的wait();
- Condition中的signal()对应Object的notify();
- Condition中的signalAll()对应Object的notifyAll()。
使用Condition实现: