2,3,4,1,0先获得了permit,相差两秒释放了permit;
5,7,6,9,8获得了permit,相差两秒释放了permit;
因为我们设置的permit是5,所有只能有五个线程获得permit。
Exchanger用来交换两个线程中的数据
示例代码如下
运行结果如下
Thread-1启动, 原数据为222, 时间为Sun Sep 29 22:18:36 CEST 2019 Thread-0启动, 原数据为111, 时间为Sun Sep 29 22:18:36 CEST 2019 Thread-0交换了数据, 交换后的数据为222, 时间为Sun Sep 29 22:18:39 CEST 2019 Thread-1交换了数据, 交换后的数据为111, 时间为Sun Sep 29 22:18:39 CEST 2019可以看到,数据发生了交换,时间差为最长时间3s。
CyclicBarrier一组线程等待对方都达到barrier point,再执行接下来的动作,barrier point是循环的,它可以重用。
示例代码如下
运行结果如下
Thread-0运行了 Thread-1运行了 Thread-2运行了 Thread-1准备等待了, 时间为Mon Sep 30 23:02:11 CEST 2019 Thread-2准备等待了, 时间为Mon Sep 30 23:02:11 CEST 2019 Thread-0准备等待了, 时间为Mon Sep 30 23:02:11 CEST 2019 CyclicBarrier的所有线程await()结束了,我运行了, 时间为Mon Sep 30 23:02:20 CEST 2019 Thread-2结束等待了, 时间为Mon Sep 30 23:02:20 CEST 2019 Thread-0结束等待了, 时间为Mon Sep 30 23:02:20 CEST 2019 Thread-1结束等待了, 时间为Mon Sep 30 23:02:20 CEST 2019Runnable线程在Thread-0,Thread-1,Thread-2 await()后运行,Runnable线程和三个线程的执行时间几乎相同。
Callable和FutureCallable
由于Runnable接口run()返回值是void类型,执行任务后无法返回结果。所以我们需要Callable接口,该接口的call()可以返回值。
Future
Future表示一个异步计算结果,Future提供了如下方法
get():获取任务执行结果
cancel():中断任务
isDone():判断任务是否执行完成
isCancelled():判断任务是否被取消
示例代码如下
public class MyThread54 implements Callable<String> { public String call() throws Exception { System.out.println("进入CallableThread的call()方法, 开始睡觉, 睡觉时间为" + new Date()); Thread.sleep(10000); return "是ss12"; } public static void main(String[] args) throws Exception { ExecutorService es = Executors.newCachedThreadPool(); MyThread54 ct = new MyThread54(); Future<String> f = es.submit(ct); es.shutdown(); Thread.sleep(5000); System.out.println("主线程等待5秒, 当前时间为" + new Date()); String str = f.get(); System.out.println("Future已拿到数据, str = " + str + ", 当前时间为" + new Date()); } }运行结果如下
进入CallableThread的call()方法, 开始睡觉, 睡觉时间为Sun Nov 03 11:00:22 CET 2019 主线程等待5秒, 当前时间为Sun Nov 03 11:00:27 CET 2019 Future已拿到数据, str = 是ss12, 当前时间为Sun Nov 03 11:00:32 CET 2019可以看到,Future在10s后拿到了返回结果。