Java Callable接口——有返回值的线程
实际开发过程中,我们常常需要等待一批线程都返回结果后,才能继续执行。《线程等待——CountDownLatch使用》中我们介绍了CountDownLatch的使用,通过使用CountDownLatch,可以实现线程等待。
JDK 1.8实现了一种更好的方式,实现线程等待与获取线程返回值,那就是Callable接口,下面我们来看看具体代码。
package com.coshaho.learn; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.apache.kafka.common.group.Time; public class CallableLearn { public static void main(String[] args) throws InterruptedException, ExecutionException { long start = System.currentTimeMillis(); MyCallableTask task1 = new MyCallableTask(); MyCallableTask task2 = new MyCallableTask(); MyCallableTask task3 = new MyCallableTask(); // 使用线程池submit方法,可以获取返回值 Future<String> future1 = FIXED_THREADPOOL.submit(task1); Future<String> future2 = FIXED_THREADPOOL.submit(task2); Future<String> future3 = FIXED_THREADPOOL.submit(task3); long end = System.currentTimeMillis(); // 任务提交不会阻塞 System.out.println("Submit task cost " + (end - start) + "ms."); System.out.println("Task1: " + future1.get()); System.out.println("Task2: " + future2.get()); System.out.println("Task3: " + future3.get()); // Future.get方法等待线程返回值 System.out.println("Get task return value cost " + (System.currentTimeMillis() - end) + "ms."); } // 大小为3的线程池 public final static ExecutorService FIXED_THREADPOOL = Executors.newFixedThreadPool(3); public static class MyCallableTask implements Callable<String> { // 睡i秒并返回信息 @Override public String call() throws Exception { Random random = new Random(); int i = random.nextInt(10) * 1000; Time.sleep(i); return "Sleep " + i + "ms."; } } }
结果
Submit task cost 3ms.
Task1: Sleep 5000ms.
Task2: Sleep 8000ms.
Task3: Sleep 8000ms.
Get task return value cost 8659ms.
三个关键点
1、 线程需要实现Callable接口
2、 线程池采用submit方法提交任务,可以获取返回值Future
3、 使用Future.get方法时,会阻塞当前线程,等待任务返回值