Java 线程池Future和FutureTask
Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务。
Future接口源码:
- 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的demo
- import java.util.ArrayList;
- import java.util.List;
- 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;
- public class Main {
- public static void main(String[] args) {
- ExecutorService executorService = Executors.newCachedThreadPool();
- List<Future<String>> resultList = new ArrayList<Future<String>>();
- // 创建10个任务并执行
- for (int i = 0; i < 10; i++) {
- // 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
- Future<String> future = executorService.submit(new TaskWithResult(i));
- // 将任务执行结果存储到List中
- resultList.add(future);
- }
- executorService.shutdown();
- // 遍历任务的结果
- for (Future<String> fs : resultList) {
- try {
- System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- executorService.shutdownNow();
- e.printStackTrace();
- return;
- }
- }
- }
- }
- class TaskWithResult implements Callable<String> {
- private int id;
- public TaskWithResult(int id) {
- this.id = id;
- }
- /**
- * 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
- *
- * @return
- * @throws Exception
- */
- public String call() throws Exception {
- System.out.println("call()方法被自动调用,干活!!! " + Thread.currentThread().getName());
- if (new Random().nextBoolean())
- throw new TaskException("Meet error in task." + Thread.currentThread().getName());
- // 一个模拟耗时的操作
- for (int i = 999999999; i > 0; i--)
- ;
- return "call()方法被自动调用,任务的结果是:" + id + " " + Thread.currentThread().getName();
- }
- }
- class TaskException extends Exception {
- public TaskException(String message) {
- super(message);
- }
- }
- call()方法被自动调用,干活!!! pool-1-thread-2
- call()方法被自动调用,干活!!! pool-1-thread-6
- call()方法被自动调用,干活!!! pool-1-thread-1
- call()方法被自动调用,任务的结果是:0 pool-1-thread-1
- call()方法被自动调用,任务的结果是:1 pool-1-thread-2
- call()方法被自动调用,干活!!! pool-1-thread-4
- call()方法被自动调用,干活!!! pool-1-thread-9
- call()方法被自动调用,干活!!! pool-1-thread-8
- call()方法被自动调用,干活!!! pool-1-thread-10
- call()方法被自动调用,干活!!! pool-1-thread-5
- call()方法被自动调用,干活!!! pool-1-thread-3
- call()方法被自动调用,干活!!! pool-1-thread-7
- call()方法被自动调用,任务的结果是:2 pool-1-thread-3
- call()方法被自动调用,任务的结果是:3 pool-1-thread-4
- java.util.concurrent.ExecutionException: com.company.TaskException: Meet error in task.pool-1-thread-5
- at java.util.concurrent.FutureTask.report(FutureTask.java:122)
- at java.util.concurrent.FutureTask.get(FutureTask.java:192)
- at com.company.Main.main(Main.java:29)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
- at java.lang.reflect.Method.invoke(Method.java:498)
- at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
- Caused by: com.company.TaskException: Meet error in task.pool-1-thread-5
- at com.company.TaskWithResult.call(Main.java:56)
- at com.company.TaskWithResult.call(Main.java:40)
- at java.util.concurrent.FutureTask.run(FutureTask.java:266)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
- at java.lang.Thread.run(Thread.java:745)
FutureTask是一个具体的实现类,ThreadPoolExecutor的submit方法返回的就是一个Future的实现,这个实现就是FutureTask的一个具体实例,FutureTask帮助实现了具体的任务执行,以及和Future接口中的get方法的关联。
Demo:
- import java.util.Date;
- import java.text.SimpleDateFormat;
- import java.util.Random;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.FutureTask;
- public class Main {
- public static void main(String[] args) {
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- // 初始化一个Callable对象和FutureTask对象
- Callable pAccount = new PrivateAccount();
- FutureTask futureTask = new FutureTask(pAccount);
- // 使用futureTask创建一个线程
- Thread pAccountThread = new Thread(futureTask);
- System.out.println("futureTask线程现在开始启动,启动时间为:" + df.format(new Date()));
- pAccountThread.start();
- System.out.println("futureTask线程开始执行其他任务");
- // 从其他账户获取总金额
- 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线程计算完毕,此时时间为" + df.format(new Date()));
- 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线程现在开始启动,启动时间为:2016-11-30 16:34:57
- futureTask线程开始执行其他任务
- 现在你在其他账户中的总金额为17113
- 等待私有账户总金额统计完毕...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 私有账户计算未完成继续等待...
- 您当前有8776在您的私有账户中
- 私有账户计算未完成继续等待...
- futureTask线程计算完毕,此时时间为2016-11-30 16:35:02
- 您现在的总金额为:17113||8776
Demo2:
- import java.util.Date;
- import java.text.SimpleDateFormat;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.FutureTask;
- public class Main {
- public static void main(String[] args) {
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- FutureTask<String> futureTask=new FutureTask<>(new Callable<String>() {
- //@Override
- public String call() throws Exception {
- // TODO Auto-generated method stub
- return "回调完成";
- }
- });
- Thread thread = new Thread(futureTask);
- System.out.println("启动时间为:" + df.format(new Date()));
- thread.start();
- try {
- String str=futureTask.get();
- if(str.equals("回调完成"))
- System.out.println("异步任务完成!");
- else
- System.out.println("Completed!");
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ExecutionException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- 启动时间为:2016-12-01 09:37:03
- 异步任务完成!
http://ifeve.com/futuretask-source/
http://www.liuinsect.com/2014/02/17/futuretask-%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/
http://blog.csdn.net/ghsau/article/details/7451464
http://blog.csdn.net/javazejian/article/details/50896505
Java 线程池Future和FutureTask的更多相关文章
- Java线程池(Callable+Future模式)
转: Java线程池(Callable+Future模式) Java线程池(Callable+Future模式) Java通过Executors提供四种线程池 1)newCachedThreadPoo ...
- Java线程池详解
一.线程池初探 所谓线程池,就是将多个线程放在一个池子里面(所谓池化技术),然后需要线程的时候不是创建一个线程,而是从线程池里面获取一个可用的线程,然后执行我们的任务.线程池的关键在于它为我们管理了多 ...
- 这么说吧,java线程池的实现原理其实很简单
好处 : 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线 ...
- java线程池技术(二): 核心ThreadPoolExecutor介绍
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...
- 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)
在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...
- 并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)
史上最清晰的线程池源码分析 鼎鼎大名的线程池.不需要多说!!!!! 这篇博客深入分析 Java 中线程池的实现. 总览 下图是 java 线程池几个相关类的继承结构: 先简单说说这个继承结构,E ...
- Java线程池 Executor框架概述
线程池的意义 循环利用线程资源,避免重复创建和销毁线程 线程池的任务是异步执行的,只要提交完成就能快速返回,可以提高应用响应性 Java线程池还有一个很重要的意义:Java线程池就是JDK 5 推出的 ...
- java线程池和中断总结
目录 java线程池和中断总结 一. 线程池的使用 二. java中断机制 中断的处理 三. 线程间通信机制总结 java线程池和中断总结 本系列文是对自己学习多线程和平时使用过程中的知识梳理,不适合 ...
- 深入分析java线程池的实现原理(转载)
前言 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线程的 ...
随机推荐
- 2017 Multi-University Training Contest - Team 7
HDU6121 Build a tree 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6121 题目意思:一棵 n 个点的完全 k 叉树,结点标号从 ...
- setMasksToBounds
setMasksToBounds 在IB中,当你使用Custom类型的Button时,你可以指定按钮的背景色.但当你运行时按钮就失去了圆角特性,你看到的仅仅是一个方块.因为custombutton没有 ...
- 1.引入jQuery
http://libs.baidu.com/jquery/2.1.4/jquery.js
- 自己开发Thinkpad电源管理程序
自己开发Thinkpad电源管理程序 - 知乎 https://zhuanlan.zhihu.com/p/20706403
- The Personal Touch Client Identification 个性化接触 客户识别
w服务器要知道和谁在交谈. HTTP The Definitive Guide Web servers may talk to thousands of different clients simul ...
- 荣誉墙项目day26 django 项目路由配置
项目路由配置文件包括:配置目录里的urls.py文件和各个app目录里的urls.py文件 1.include()——从项目主路由分配到各APP主路由 from django.conf.urls im ...
- Python在运维工作中的经典应用之ansible
1.安装ansible wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo curl -o /e ...
- Android Volley全然解析(四),带你从源代码的角度理解Volley
版权声明:本文出自郭霖的博客,转载必须注明出处. https://blog.csdn.net/sinyu890807/article/details/17656437 转载请注明出处:http://b ...
- 001-linux scp文件拷贝
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...
- ReSharper Ultimate 2017 下载地址及破解方法
https://download.jetbrains.8686c.com/resharper/JetBrains.ReSharperUltimate.2017.1.2.exe 安装完成后,打开vs ...