1、使用executor.isTerminated()判断线程池中的线程是否执行完成
/** * @author chuan * @title: ThreadResultTest * @description: TODO(获取Thread的返回值) */ public class ThreadResultTest implements Runnable{ /** * 在没有获取Thread的返回值之前,先判断一下线程是否执行完成 */ private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class); // 线程安全的List集合 private static List<String> sycnList = Collections.synchronizedList(new ArrayList<String>()); // 创建一个线程池 private static ExecutorService executor = Executors.newFixedThreadPool(1); private int count = 0; public ThreadResultTest(int count) { this.count = count; } @Override public void run() { try { sycnList.add("add data into collection"); Thread.currentThread().setName("Thread-Pool"); int nextInt = new Random().nextInt(100); Thread.sleep(nextInt); logger.info("execute result : " + count); } catch (Exception e) { e.printStackTrace(); logger.error("thread execute error info:{},{}",e.getMessage(),e); } } public static void main(String[] args) throws Exception{ for (int i = 0; i < 12; i++) { executor.execute(new ThreadResultTest(i)); } System.out.println("execute info : 线程已添加到队列,正在执行中..."); executor.shutdown(); while (true) { Thread.sleep(1000); if(executor.isTerminated()) { System.out.printf("execute result : %s","所有的线程执行完毕!"); break; } } } }
输出结果:
2、通过while循环检测获取线程结果
/** * @author chuan * @title: ThreadResultTest * @description: TODO(获取Thread的返回值-while) */ public class ThreadResultTest implements Runnable{ private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class); private Object result; public Object getResult() { return result;} @Override public void run() { try { System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ..."); Thread.sleep(6000); // 模拟获取结果 result = Integer.valueOf(new Random().nextInt(100)); System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end!"); } catch (Exception e) { logger.error("thread execute error info:{},{}",e.getMessage(),e); } } public static void main(String[] args) throws Exception{ ThreadResultTest callback = new ThreadResultTest(); final String threadName = "Thread-Name"; Thread thread = new Thread(callback,threadName); thread.start(); // 循环检测线程的值 while (true){ if(callback.getResult()!=null){ System.out.printf("execute result : %s",callback.getResult()); break; } // 定时检测、提高一下性能 Thread.sleep(1000); logger.info("execute check up info : " + callback.getResult()); } } }
输出结果:
3、通过wait、notify组合方式获取线程的值
/** * @author chuan * @title: ThreadResultTest * @description: TODO(获取Thread的返回值-wait和notify组合) */ public class ThreadResultTest implements Runnable{ private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class); private Object result; public Object getResult() { return result;} @Override public void run() { try { System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ..."); Thread.sleep(6000); // 模拟获取结果 result = Integer.valueOf(new Random().nextInt(100)); //唤醒wait的对象 synchronized (this){ this.notify(); } System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end!"); } catch (Exception e) { logger.error("thread execute error info:{},{}",e.getMessage(),e); } } public static void main(String[] args) throws Exception { ThreadResultTest callback = new ThreadResultTest(); final String threadName = "Thread-Name"; Thread thread = new Thread(callback, threadName); thread.start(); // 循环检测线程的值 while (true) { if (callback.getResult() == null) { System.out.println("execute result : " + callback.getResult()); // 如果获取的线程的值为null,则线程进入wait()状态,等待唤醒 synchronized (callback) { try { callback.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } if (callback.getResult() != null) { logger.info("execute check up info : " + callback.getResult()); break; } } } }
输出结果:
4、使用LockSupport获取线程的值
/** * @author chuan * @title: ThreadResultTest * @description: TODO(获取Thread的返回值-LockSupport) */ public class ThreadResultTest implements Runnable{ private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class); private Object result; public Object getResult() { return result;} Thread currRun; ThreadResultTest(Thread threadRun){ this.currRun = threadRun; } @Override public void run() { try { System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ..."); Thread.sleep(6000); // 模拟获取结果 result = Integer.valueOf(new Random().nextInt(100)); //唤醒wait的对象 synchronized (this){ LockSupport.unpark(currRun); } System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end!"); } catch (Exception e) { logger.error("thread execute error info:{},{}",e.getMessage(),e); } } public static void main(String[] args) throws Exception { ThreadResultTest callback = new ThreadResultTest(Thread.currentThread()); final String threadName = "Thread-Name"; Thread thread = new Thread(callback, threadName); thread.start(); // 循环检测线程的值 while (true) { if (callback.getResult() == null) { System.out.println("execute result : " + callback.getResult()); LockSupport.park(); } if (callback.getResult() != null) { logger.info("execute check up info : " + callback.getResult()); break; } } } }
输出结果:
5、使用Callable获取线程的值
/** * @author chuan * @title: ThreadResultTest * @description: TODO(获取Thread的返回值-Callable) */ public class ThreadResultTest implements Callable<Object> { @Override public Object call() throws Exception { System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ..."); Thread.sleep(2000); // 模拟获取结果 Object result = Integer.valueOf(new Random().nextInt(100)); System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end ! "); return result; } public static void main(String[] args) throws Exception { ThreadResultTest callback = new ThreadResultTest(); ExecutorService es = Executors.newSingleThreadExecutor(); Future<Object> future = es.submit(callback); System.out.println("execute result:"+future.get()); es.shutdown(); } }
输出结果:
这样就能很简单的获取到线程的值,获取返回值的方式是future.get(),这是一个阻塞方法;在子线程执行完(return)之前会一直阻塞。Callable本身就一接口,没什么玄机,玄机在 Future 或者说FutureTask上。
FutureTask是Future接口和Runnable接口的实现类。FutureTask是怎么和Callable关联上的?
- 经ExecutorService的作用,Callable会最终赋值给FutureTask的成员变量
- 通过查看源码、可以得出经过一系列调用过程,最终会调用Callable的call方法
其中get()是获取值的,它的逻辑并不复杂:
- 判断状态,如果此时还未执行完,或者说还未给成员变量outcome(call() 方法返回值的引用)赋值,阻塞
- 如果此时已经给outcome赋值,则将该对象返回