标签:初始化 包括 cut 线程 作业 ota 提交 one runnable
在传统的多线程实现方式中(继承Thread和实现Runnable)无法直接获取线程执行的返回结果,如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。
从Java 1.5开始,java.util.concurrent包中提供了 Callable和 Future两个接口,通过它们就可以在任务执行完毕之后得到任务执行结果。
Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。
Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行
取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果。
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; }
也就是说Future提供了三种功能:
FutureTask是为了弥补Thread的不足而设计的,它可以让程序员准确地知道线程什么时候执行完成并获得到线程执行完成后返回的结果(如果有需要)。
FutureTask是一种可以取消的异步的计算任务。它的计算是通过Callable实现的,它等价于可以携带结果的Runnable,并且有三个状态:等待、运行和完成。完成包括所有计算以任意的方式结束,包括正常结束、取消和异常。
Executor框架利用FutureTask来完成异步任务,并可以用来进行任何潜在的耗时的计算。一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
Example1:
package cn.com.example.concurrent.future; import java.util.concurrent.*; /** * Created by Jack on 2017/1/24. */ public class RunnableFutureTask { /** * ExecutorService */ static ExecutorService mExecutor = Executors.newSingleThreadExecutor(); /** * @param args */ public static void main(String[] args) { runnableDemo(); futureDemo(); } /** * runnable, 无返回值 */ static void runnableDemo() { new Thread(new Runnable() { @Override public void run() { System.out.println("runnable demo : " + fibc(20)); } }).start(); } /** * 其中Runnable实现的是void run()方法,无返回值;Callable实现的是 V * call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下 * ,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。 */ static void futureDemo() { try { /** * 提交runnable则没有返回值, future没有数据 */ Future<?> result = mExecutor.submit(new Runnable() { @Override public void run() { fibc(20); } }); System.out.println("future result from runnable : " + result.get()); /** * 提交Callable, 有返回值, future中能够获取返回值 */ Future<Integer> result2 = mExecutor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { return fibc(20); } }); System.out.println("future result from callable : " + result2.get()); /** * FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口, * 另外它还可以包装Runnable(实际上会转换为Callable)和Callable * <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行 * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。 */ FutureTask<Integer> futureTask = new FutureTask<Integer>( new Callable<Integer>() { @Override public Integer call() throws Exception { return fibc(20); } }); // 提交futureTask mExecutor.submit(futureTask); System.out.println("future result from futureTask : " + futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } /** * 效率底下的斐波那契数列, 耗时的操作 * * @param num * @return */ static int fibc(int num) { if (num == 0) { return 0; } if (num == 1) { return 1; } return fibc(num - 1) + fibc(num - 2); } }
结果:
runnable demo : 6765 future result from runnable : null future result from callable : 6765 future result from futureTask : 6765
Example2:
package cn.com.example.concurrent.future; import java.util.Random; import java.util.concurrent.*; /** * Created by Jack on 2017/1/24. */ public class RunnableFutureTask { public static void main(String[] args) { // 初始化一个Callable对象和FutureTask对象 Callable pAccount = new PrivateAccount(); FutureTask futureTask = new FutureTask(pAccount); // 使用futureTask创建一个线程 Thread pAccountThread = new Thread(futureTask); System.out.println("futureTask线程现在开始启动,启动时间为:" + System.nanoTime()); pAccountThread.start(); System.out.println("主线程开始执行其他任务"); // 从其他账户获取总金额 int totalMoney = new Random().nextInt(100000); System.out.println("现在你在其他账户中的总金额为" + totalMoney); System.out.println("等待私有账户总金额统计完毕..."); // 测试后台的计算线程是否完成,如果未完成则等待 while (!futureTask.isDone()) { try { Thread.sleep(500); System.out.println("私有账户计算未完成继续等待..."); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("futureTask线程计算完毕,此时时间为" + System.nanoTime()); Integer privateAccountMoney = null; try { privateAccountMoney = (Integer) futureTask.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("您现在的总金额为:" + totalMoney + privateAccountMoney.intValue()); } } class PrivateAccount implements Callable { Integer totalMoney; @Override public Object call() throws Exception { Thread.sleep(5000); totalMoney = new Integer(new Random().nextInt(10000)); System.out.println("您当前有" + totalMoney + "在您的私有账户中"); return totalMoney; } }
结果:
futureTask线程现在开始启动,启动时间为:88171383410225 主线程开始执行其他任务 现在你在其他账户中的总金额为2838 等待私有账户总金额统计完毕... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 私有账户计算未完成继续等待... 您当前有9238在您的私有账户中 私有账户计算未完成继续等待... futureTask线程计算完毕,此时时间为88176389195218 您现在的总金额为:28389238
java.util.concuttent Callable Future详解
标签:初始化 包括 cut 线程 作业 ota 提交 one runnable
原文地址:http://www.cnblogs.com/Zombie-Xian/p/6347580.html