Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值。但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get()方法时任务尚未执行完,则调用get()方法时一直阻塞到此任务完成。如果前面的任务耗时很多,则后面的任务调用get()方法就呈阻塞状态,大大影响运行效率。主线程不能保证首先获得的是最先完成任务的返回值,这是Future的缺点。

public class MyCallable implements Callable<String> {
private int age; public MyCallable(int age) {
super();
this.age = age;
}
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(8);
return "返回值 年龄是:" + age;
} public static void main(String[] args) {
MyCallable myCallable = new MyCallable(22);
int corePoolSize = 2;
int maximumPoolSize = 3;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
Future<String> future = threadPoolExecutor.submit(myCallable);
try {
System.out.println(System.currentTimeMillis());
String string = future.get();
System.out.println(string);
System.out.println(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}

打印结果如下:

1470904027660
返回值 年龄是:22
1470904035663

从打印结果看,可见get()方法具有阻塞的特性。

方法submit()不仅可以传入Callable对象,还可以传入Runnable对象,submit()方法支持有返回值和无返回值。

public class Run {
public static void main(String[] args) {
try {
Runnable runnable = new Runnable() { @Override
public void run() {
System.out.println("打印的信息");
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
Future future = executorService.submit(runnable);
System.out.println(future.get() + " " + future.isDone());
} catch (Exception e) {
e.printStackTrace();
}
}
}

打印结果如下:

打印的信息
null true

方法isDone()无阻塞特性。


使用ExecutorService接口中的方法submit(Runnable, T result)
public class User {
private String username;
private String password;
//省略getter setter
} public class MyRunnable implements Runnable {
private User user;
public MyRunnable(User user) {
super();
this.user = user;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
user.setUsername("admin");
user.setPassword("123456");
}
} public class Main {
FutureTask task;
public static void main(String[] args) {
try {
User user = new User();
MyRunnable myRunnable = new MyRunnable(user);
int corePoolSize = 10;
int maximumPoolSize = 10;
int keepAliveTime = 10;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
Future<User> future = executor.submit(myRunnable, user);
System.out.println(System.currentTimeMillis());
System.out.println(user.getUsername() + "-" + user.getPassword());
user = future.get();
System.out.println(user.getUsername() + "-" + user.getPassword());
System.out.println(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}

控制台打印结果如下:

1470908214853
null-null
admin-123456
1470908216855

Java并发编程核心方法与框架-Future和Callable的使用的更多相关文章

  1. Java并发编程核心方法与框架-CountDownLatch的使用

    Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...

  2. Java并发编程核心方法与框架-Fork-Join分治编程(一)

    在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...

  3. Java并发编程核心方法与框架-CompletionService的使用

    接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...

  4. Java并发编程核心方法与框架-TheadPoolExecutor的使用

    类ThreadPoolExecutor最常使用的构造方法是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAli ...

  5. Java并发编程核心方法与框架-Semaphore的使用

    Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...

  6. Java并发编程核心方法与框架-ScheduledExecutorService的使用

    类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...

  7. Java并发编程核心方法与框架-ExecutorService的使用

    在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...

  8. Java并发编程核心方法与框架-Executors的使用

    合理利用线程池能够带来三个好处 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可管理性.线程是稀 ...

  9. Java并发编程核心方法与框架-phaser的使用

    arriveAndAwaitAdvance()方法 arriveAndAwaitAdvance()作用是当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障执行. public cla ...

随机推荐

  1. 绑定: 与 Element 绑定, 与 Indexer 绑定, TargetNullValue, FallbackValue

    介绍背水一战 Windows 10 之 绑定 与 Element 绑定 与 Indexer 绑定 TargetNullValue - 当绑定数据为 null 时显示的值 FallbackValue - ...

  2. 【BZOJ-2839】集合计数 容斥原理 + 线性推逆元 + 排列组合

    2839: 集合计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 229  Solved: 120[Submit][Status][Discuss] ...

  3. bzoj3262: 陌上花开(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  4. 洛谷P1565 牛宫

    题目描述 AP 神牛准备给自己盖一座很华丽的宫殿.于是,他看中了一块N*M 的矩形空地. 空地中每个格子都有自己的海拔高度.AP 想让他的宫殿的平均海拔在海平面之上(假设 海平面的高度是0,平均数都会 ...

  5. dedecms /include/filter.inc.php Local Variable Overriding

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 filter.inc.php这个文件在系统配置文件之后,里面有forea ...

  6. windows下安装使用Composer记录

    一直以来都是直接下载类库文件放到项目中使用 Composer是一个PHP依赖管理工具,有了它,就可以对依赖的包进行统一管理,而且在项目中可以实现自动加载 安装和使用composer 下载并且运行 Co ...

  7. 加州大学伯克利分校Stat2.3x Inference 统计推断学习笔记: Section 5 Window to a Wider World

    Stat2.3x Inference(统计推断)课程由加州大学伯克利分校(University of California, Berkeley)于2014年在edX平台讲授. PDF笔记下载(Acad ...

  8. HDU 5904 LCIS (最长公共上升序列)

    传送门 Description Alex has two sequences a1,a2,...,an and b1,b2,...,bm. He wants find a longest common ...

  9. python pep8

    有这个自动的规范检查工具 pip install pep8 具体使用不说了 ==. 百度一堆  http://blog.sae.sina.com.cn/archives/4781  看这里

  10. DOM参考手册及事件参考手册

    给全局HTML DOM元素增加函数的方法 HTMLElement.prototype.hasClass = function (className) { return new RegExp(" ...