Java并发编程核心方法与框架-ExecutorService的使用
在ThreadPoolExecutor中使用ExecutorService中的方法
方法invokeAny()和invokeAll()具有阻塞特性
方法invokeAny()取得第一个完成任务的结果值,当第一次任务执行完成后,会调用interrupt()方法将其他任务中断,所以在这些任务中可以结合if(Thread.currentThread().isInterrupted() == true)来决定任务是否继续运行。
- 无if(Thread.currentThread().isInterrupted() == true)代码:已经获得第一个运行的结果值后,其他线程继续运行。
- 有if(Thread.currentThread().isInterrupted() == true)代码:已经获得第一个运行的结果值后,其他线程如果使用throw new InterruptedExeception()代码则这些线程中断,虽然throw抛出了异常,但在main线程中并不能捕获异常。如果要捕获异常,则需要在Callable中使用try-catch进行捕获。
方法invokeAll()等全部线程任务执行完毕后,取得全部完成任务的结果值。
public class MyCallableA implements Callable<string> {
@Override
public String call() throws Exception {
System.out.println("MyCallableA.call() begin " + System.currentTimeMillis());
for (int i = 0; i < 123456; i++) {
Math.random();
Math.random();
Math.random();
System.out.println("MyCallableA.call() " + i);
}
System.out.println("MyCallableA.call() end " + System.currentTimeMillis());
return "MyCallableA_return";
}
}
public class MyCallableB1 implements Callable<string> {
@Override
public String call() throws Exception {
System.out.println("MyCallableB1.call() begin " + System.currentTimeMillis());
for (int i = 0; i < 223456; i++) {
Math.random();
Math.random();
Math.random();
System.out.println("MyCallableB1.call() " + i);
}
System.out.println("MyCallableB1.call() end " + System.currentTimeMillis());
return "MyCallableB1_return";
}
}
public class MyCallableB2 implements Callable<string> {
@Override
public String call() throws Exception {
System.out.println("MyCallableB2.call() begin " + System.currentTimeMillis());
for (int i = 0; i < 223456; i++) {
if (!Thread.interrupted()) {
Math.random();
Math.random();
Math.random();
System.out.println("MyCallableB2.call() " + i);
} else {
System.out.println("MyCallableB2.call() 抛出异常中断了");
throw new InterruptedException();
}
}
System.out.println("MyCallableB2.call() end " + System.currentTimeMillis());
return "MyCallableB2_return";
}
}
public class Run1 {
public static void main(String[] args) {
try {
List list = new ArrayList<>();
list.add(new MyCallableA());
list.add(new MyCallableB1());
ExecutorService executorService = Executors.newCachedThreadPool();
String getValueA = executorService.invokeAny(list);
System.out.println("Run1.main() getValueA=" + getValueA);
System.out.println("Run1.main() end");
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果如下:
MyCallableA.call() 98
MyCallableA.call() 99
MyCallableA.call() end 1472041166456
Run1.main() getValueA=MyCallableA_return
Run1.main() end
MyCallableB1.call() 60
MyCallableB1.call() 61
MyCallableB1.call() 62
虽然方法invokeAny()已经取得returnA的值,但线程B还在继续运行中,直到运行完毕。
使用MyCallable2类
public class MyCallableB2 implements Callable<string> {
@Override
public String call() throws Exception {
System.out.println("MyCallableB2.call() begin " + System.currentTimeMillis());
for (int i = 0; i < 500; i++) {
if (!Thread.interrupted()) {
Math.random();
Math.random();
Math.random();
System.out.println("MyCallableB2.call() " + i);
} else {
System.out.println("MyCallableB2.call() 抛出异常中断了");
throw new InterruptedException();
}
}
System.out.println("MyCallableB2.call() end " + System.currentTimeMillis());
return "MyCallableB2_return";
}
}
public class Run2 {
public static void main(String[] args) {
try {
List list = new ArrayList<>();
list.add(new MyCallableA());
list.add(new MyCallableB2());
ExecutorService executorService = Executors.newCachedThreadPool();
String getValueA = executorService.invokeAny(list);
System.out.println("Run1.main() getValueA=" + getValueA);
System.out.println("Run1.main() end");
} catch (Exception e) {
e.printStackTrace();
}
}
}
此时控制台输出结果如下:
......
MyCallableA.call() 95
MyCallableA.call() 96
MyCallableA.call() 97
MyCallableA.call() 98
MyCallableA.call() 99
MyCallableA.call() end 1472041795166
Run1.main() getValueA=MyCallableA_return
Run1.main() end
MyCallableB2.call() 抛出异常中断了
线程A执行完毕后,线程池将线程B设置为中断interrupted状态,而线程B可以自定义对中断interruptted状态进行处理,可以使用Thread.interrupted()结合throw new InterruptedException()进行处理。
方法invokeAny()与执行慢的任务异常
快的任务优先执行完毕之后,执行慢的任务出现异常时,默认情况下不会在控制台输出异常信息。可以使用try-catch捕获异常。
....//代码见P212
也可以在Callable中使用try-catch捕获异常信息,此时不能在main线程中捕获到异常。
....//代码见P214
方法invokeAny()与执行快的任务异常
执行快的任务出现异常时,默认情况下是不在控制台输出异常信息的。除非显式使用try-catch捕获,而等待执行慢的任务返回结果值。
....//代码见P217
Java并发编程核心方法与框架-ExecutorService的使用的更多相关文章
- Java并发编程核心方法与框架-CountDownLatch的使用
Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...
- Java并发编程核心方法与框架-Fork-Join分治编程(一)
在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...
- Java并发编程核心方法与框架-CompletionService的使用
接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...
- Java并发编程核心方法与框架-TheadPoolExecutor的使用
类ThreadPoolExecutor最常使用的构造方法是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAli ...
- Java并发编程核心方法与框架-Semaphore的使用
Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...
- Java并发编程核心方法与框架-Future和Callable的使用
Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值.但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get ...
- Java并发编程核心方法与框架-Executors的使用
合理利用线程池能够带来三个好处 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可管理性.线程是稀 ...
- Java并发编程核心方法与框架-CyclicBarrier的使用
CyclicBarrier类似于CountDownLatch也是个计数器,不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了Cyc ...
- Java并发编程核心方法与框架-ScheduledExecutorService的使用
类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...
随机推荐
- 由一段JS代码引发的思考
不知道大家在编程的时候有没有遇到过这种情况,就是在循环遍历删除一部分内容的时候,发现只能删除其中一部分,而另一部分却总也删不掉,然后觉得自己的逻辑没有问题啊,于是陷入了深深的抑郁之中…… 昨天在处理一 ...
- [模板] 2-SAT
昨天早上在准备省队集训,发现自己连2-SAT是什么都不知道,于是一早上都投身于2-SAT模板中,终于有个结果. 思路如下: 1.根据条件表达式建边: 2.缩环: 3.判断是否可行: 4.根据缩完环的图 ...
- js-JavaScript高级程序设计学习笔记6
第八章 BOM 1.BOM的核心对象是window,他表示浏览器的一个实例.在浏览器中,window对象有双重角色,它既是通过JS访问浏览器窗口的一个接口,又是ES规定的Global对象. 2.定义全 ...
- Leetcode 257. Binary Tree Paths
Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...
- 【bzoj3884】 上帝与集合的正确用法
http://www.lydsy.com/JudgeOnline/problem.php?id=3884 (题目链接) 题意 求 Solution 解决的关键: 当${n>φ(p)}$,有$${ ...
- C语言之流的重定向
写c的小程序断不了需要输入输出,手动输入可太麻烦了.下面介绍IO的重定向方式: .重定向标准输入输出和错误,直接在命令行使用符号< > > >> >>等,还可 ...
- poj2187 旋转卡(qia)壳(ke)
题意:求凸包的直径 关于对踵点对.旋转卡壳算法的介绍可以参考这里: http://www.cnblogs.com/Booble/archive/2011/04/03/2004865.html http ...
- Linux process authority、the security risks in running process with high authority
catalog . Linux进程权限原理 . 最小权限原则 - 进程降权运行最佳实践 . 进程权限控制包含的攻防向量 . 进程高权限安全风险检查技术方案 1. Linux进程权限原理 我们知道,Li ...
- AngularJs Angular数据类型判断
angular.isArray 判断括号内的值是否为数组. 格式:angular.isArray(value); value: 被判断是否为数组的值. ------------------------ ...
- POJ1741:tree
传送门 时隔一个月再次写点分治,比上一次要深入理解很多了.(虽然代码还是写不熟 模板题,不多说 //POJ 1741 //by Cydiater //2016.9.22 #include <cs ...