java高并发系列已经学了不少东西了,本篇文章,我们用前面学的知识来实现一个需求:
在一个线程中需要获取其他线程的执行结果,能想到几种方式?各有什么优缺点?
结合这个需求,我们使用6种方式,来对之前学过的知识点做一个回顾,加深记忆。
方式1:Thread的join()方法实现
代码:
package com.itsoku.chat31;import java.sql.Time;import java.util.concurrent.*;/*** 跟着阿里p7学并发,微信公众号:javacode2018*/public class Demo1 {//用于封装结果static class Result<T> {T result;public T getResult() {return result;}public void setResult(T result) {this.result = result;}}public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println(System.currentTimeMillis());//用于存放子线程执行的结果Result<Integer> result = new Result<>();//创建一个子线程Thread thread = new Thread(() -> {try {TimeUnit.SECONDS.sleep(3);result.setResult(10);} catch (InterruptedException e) {e.printStackTrace();}});thread.start();//让主线程等待thread线程执行完毕之后再继续,join方法会让当前线程阻塞thread.join();//获取thread线程的执行结果Integer rs = result.getResult();System.out.println(System.currentTimeMillis());System.out.println(System.currentTimeMillis() + ":" + rs);}}
输出:
156673316263615667331656921566733165692:10
代码中通过join方式阻塞了当前主线程,当thread线程执行完毕之后,join方法才会继续执行。
关于join()方法和线程更详细的使用,可以参考:线程的基本操作
方式2:CountDownLatch实现
代码:
package com.itsoku.chat31;import java.util.concurrent.*;/*** 跟着阿里p7学并发,微信公众号:javacode2018*/public class Demo2 {//用于封装结果static class Result<T> {T result;public T getResult() {return result;}public void setResult(T result) {this.result = result;}}public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println(System.currentTimeMillis());CountDownLatch countDownLatch = new CountDownLatch(1);//用于存放子线程执行的结果Demo1.Result<Integer> result = new Demo1.Result<>();//创建一个子线程Thread thread = new Thread(() -> {try {TimeUnit.SECONDS.sleep(3);result.setResult(10);} catch (InterruptedException e) {e.printStackTrace();}finally {countDownLatch.countDown();}});thread.start();//countDownLatch.await()会让当前线程阻塞,当countDownLatch中的计数器变为0的时候,await方法会返回countDownLatch.await();//获取thread线程的执行结果Integer rs = result.getResult();System.out.println(System.currentTimeMillis());System.out.println(System.currentTimeMillis() + ":" + rs);}}
输出:
156673372040615667337234531566733723453:10
上面代码也达到了预期效果,使用CountDownLatch可以让一个或者多个线程等待一批线程完成之后,自己再继续;CountDownLatch更详细的介绍见:JUC中等待多线程完成的工具类CountDownLatch,必备技能
方式3:ExecutorService.submit方法实现
代码:
package com.itsoku.chat31;import java.util.concurrent.*;/*** 跟着阿里p7学并发,微信公众号:javacode2018*/public class Demo3 {public static void main(String[] args) throws ExecutionException, InterruptedException {//创建一个线程池ExecutorService executorService = Executors.newCachedThreadPool();System.out.println(System.currentTimeMillis());Future<Integer> future = executorService.submit(() -> {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 10;});//关闭线程池executorService.shutdown();System.out.println(System.currentTimeMillis());Integer result = future.get();System.out.println(System.currentTimeMillis() + ":" + result);}}
输出:
156673411993815667341199891566734122989:10
使用ExecutorService.submit方法实现的,此方法返回一个Future,future.get()会让当前线程阻塞,直到Future关联的任务执行完毕。
相关知识:
方式4:FutureTask方式1
代码:
package com.itsoku.chat31;import java.util.concurrent.*;/*** 跟着阿里p7学并发,微信公众号:javacode2018*/public class Demo4 {public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println(System.currentTimeMillis());//创建一个FutureTaskFutureTask<Integer> futureTask = new FutureTask<>(() -> {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 10;});//将futureTask传递一个线程运行new Thread(futureTask).start();System.out.println(System.currentTimeMillis());//futureTask.get()会阻塞当前线程,直到futureTask执行完毕Integer result = futureTask.get();System.out.println(System.currentTimeMillis() + ":" + result);}}
输出:
156673635031415667363503581566736353360:10
代码中使用FutureTask实现的,FutureTask实现了Runnable接口,并且内部带返回值,所以可以传递给Thread直接运行,futureTask.get()会阻塞当前线程,直到FutureTask构造方法传递的任务执行完毕,get方法才会返回。关于FutureTask详细使用,请参考:
方式5:FutureTask方式2
代码:
package com.itsoku.chat31;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;import java.util.concurrent.TimeUnit;/*** 跟着阿里p7学并发,微信公众号:javacode2018*/public class Demo5 {public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println(System.currentTimeMillis());//创建一个FutureTaskFutureTask<Integer> futureTask = new FutureTask<>(() -> 10);//将futureTask传递一个线程运行new Thread(() -> {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}futureTask.run();}).start();System.out.println(System.currentTimeMillis());//futureTask.get()会阻塞当前线程,直到futureTask执行完毕Integer result = futureTask.get();System.out.println(System.currentTimeMillis() + ":" + result);}}
输出:
156673631992515667363199701566736322972:10
创建了一个FutureTask对象,调用futureTask.get()会阻塞当前线程,子线程中休眠了3秒,然后调用futureTask.run();当futureTask的run()方法执行完毕之后,futureTask.get()会从阻塞中返回。
注意:这种方式和方式4的不同点。
关于FutureTask详细使用,请参考:JUC中的Executor框架详解1
方式6:CompletableFuture方式实现
代码:
package com.itsoku.chat31;import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;import java.util.concurrent.TimeUnit;/*** 跟着阿里p7学并发,微信公众号:javacode2018*/public class Demo6 {public static void main(String[] args) throws ExecutionException, InterruptedException {System.out.println(System.currentTimeMillis());CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return 10;});System.out.println(System.currentTimeMillis());//futureTask.get()会阻塞当前线程,直到futureTask执行完毕Integer result = completableFuture.get();System.out.println(System.currentTimeMillis() + ":" + result);}}
输出:
156673620534815667362054281566736208429:10
CompletableFuture.supplyAsync可以用来异步执行一个带返回值的任务,调用completableFuture.get()
会阻塞当前线程,直到任务执行完毕,get方法才会返回。
关于CompletableFuture更详细的使用见:JUC中工具类CompletableFuture,必备技能
最新资料
注意:本文归作者所有,未经作者允许,不得转载