常见的实现多线程的方式有两种,1.继承Thread类,2.实现Runnable接口,这两种实现方式无法得到线程执行的结果.所以如果想要得到线程执行最终的结果,就可以使用Callable接口与Future接口.
Callable
Callable与Runnable两者都是接口,功能基本上相似的.都是是个任务类.
先看Runnable接口,接口里面仅有一个方法.可以看到run()方法的返回值是void类型,所以是没有返回值的.
public interface Runnable { public abstract void run(); }
Callable接口里面有一个相似的Call()方法,源码如下.可以看出Callable是支持泛型的.
public interface Callable<V> { V call() throws Exception; }
Future
Future接口在java.util.concurrent包下面,可以进行正在的执行的取消,判断任务是否执行完成,以及获取线程执行结果等
源码如下:
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
- cancel方法的用来进行取消任务的执行.参数mayInterruptIfRunning表示是否可以取消正在执行的任务.
(1) 任务尚未启动:不管mayInterruptIfRunning设置为false还是true,由于任务还未执行,返回值为true,并且任务永不执行.
(2)任务执行中:当mayInterruptIfRunning为false的时候,表示任务不能被取消,所以方法返回值为false.当设置为true的时候,表示任务可以取消,方法的返回值为true.
(3)任务执行完成:不管mayInterruptIfRunning设置为false还是true,由于任务已经完成,无法取消,所以方法返回值为false.
- isCancelled()方法在任务正常完成之前取消,返回值为true.
- isDone()方法如果任务已经完成,返回值为true.
- V get()方法获取任务执行的结果,方法会一直阻塞,直到任务执行完成拿到返回值.
- V get(long timeout,TimeUnit unit)方法在指定的时间内进行是否能够获取到返回值,如不能,返回为null.
Future接口无法创建对象,常见使用就是Future接口的间接实现类FutureTask<V>.
FutureTask
FutureTask<V>类实现了RunnableFuture<V>接口.如下:
public class FutureTask<V> implements RunnableFuture<V> {}
而RunnableFuture<V>接口是多继承的接口,继承了Runnable接口和Future<V>接口.
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
可知FutureTask类里面有Future接口方法的所有实现和Runnable接口的方法实现.所以作为Runnable的实现类可以被多线程执行,又可以利用Future的get()方法获取线程最终的执行结果.
FutureTask里面两个构造器.
public FutureTask(Callable<V> callable) {} public FutureTask(Runnable runnable, V result) {}
第一个构造器,当创建一个FutureTask对象的,就执行给定的Callable,第二构造器传入Runnable,result是线程成功执行要返回的结果.不需要特定的结果,可以将result置为null.
示例
1.FutureTask+Thread/FutureTaskFutureTask+ExecutorService,FutureTask简介实现Runnable,所以可以作为Runnable被线程和线程池当做任务类来执行.
public class CallableTask implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("subThread"+" is running"); int result = 0; for (int i = 0; i < 10; i++) { result += i; } Thread.sleep(3000); return result; } }
public class FutureDemo { public static void main(String[] args) { // 创建任务类对象 CallableTask task = new CallableTask(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); Thread thread = new Thread(futureTask); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("mainThread is running"); // 判断子线程的任务是否执行完成 if (!futureTask.isDone()) { try { System.out.println("subThread is not finished"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } try { System.out.println("callableTask result:" + futureTask.get()); } catch (Exception e) { e.printStackTrace(); } } }
执行结果
subThread is running mainThread is running subThread is not finished callableTask result:4950
2.:Future+ExecutorService;此例子是将Callable任务类CallableTask扔到线程池里面执行.
public class CallableTask implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("subThread"+" is running"); int result = 0; for (int i = 0; i < 10; i++) { result += i; } Thread.sleep(3000); return result; } }
public class FutureDemo { public static void main(String[] args) { // 创建任务类对象 CallableTask task = new CallableTask(); ExecutorService service = Executors.newCachedThreadPool(); //线程池执行Callable任务类 Future<Integer> future = service.submit(task); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("mainThread is running"); // 判断子线程的任务是否执行完成 if (!future.isDone()) { try { System.out.println("subThread is not finished"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } try { System.out.println("callableTask result:" + future.get()); } catch (Exception e) { e.printStackTrace(); } } }
执行结果:
subThread is running mainThread is running subThread is not finished callableTask result:45
3.FutureTask的集合形式:这种与前面的单个FutureTask类似.
public class ComputeTask implements Callable<Integer> { private int result; private String name; public ComputeTask(int result, String name) { this.result = result; this.name = name; } @Override public Integer call() throws Exception { for (int i = 0; i < 10; i++) { result += i; } System.out.println("subThread-" + name + " computing task has finished"); return result; } }
public class ComputeTaskDemo { public static void main(String[] args) { // 创建一个任务的集合 List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>(); ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { FutureTask<Integer> futureTask = new FutureTask<Integer>(new ComputeTask(i, "task" + i)); // 将任务添加到集合中 taskList.add(futureTask); // 将任务提交给线程 executorService.submit(futureTask); } // 获取所有的任务的计算结果 int totalResult = 0; for (FutureTask<Integer> future : taskList) { try { totalResult += future.get(); } catch (Exception e) { e.printStackTrace(); } } executorService.shutdown(); System.out.println("the final result is" + totalResult); } }
执行结果是:
subThread-task0 computing task has finished subThread-task2 computing task has finished subThread-task3 computing task has finished subThread-task1 computing task has finished subThread-task5 computing task has finished subThread-task4 computing task has finished subThread-task6 computing task has finished subThread-task7 computing task has finished subThread-task8 computing task has finished subThread-task9 computing task has finished the final result is495
参考文章
《Java并发编程实战》
https://www.cnblogs.com/ruiati/p/6133174.html