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 ...
随机推荐
- SVN安装配置和使用教程
注意:location :为安装文件位置,Repositories:为管理的代码仓库的位置,若选中Use secure connection前面的Checkbox,则表示安全连接[https],这里的 ...
- bash中不可以用字符串做数组下标
bash中可以用字符串做数组下标吗例如 test["abc"]=1------解决方案-------------------- 好像是误会,是awk里可以,bash shell里不 ...
- Matlab的实时编辑器(Live Script)
Matlab的实时编辑器(Live Script) 看到伟哥换用了matlab2016a,里面集成了acf行人检测算法,感觉挺好的,索性也从matlab2014a跨越到matlab2016a. 安装后 ...
- LaTeX 笔记---Q&A
Q: Is it possible to check which package do I need to install to get certain .sty file from tlmgr ra ...
- JSP重定向小例子(不讲原理)
编写一个JSP页面lucknum.jsp,产生0-9之间的随机数作为用户幸运数字,将其保存到会话中,并重定向到另一个页面showLuckNum.jsp中,在该页面中将用户的幸运数字显示出来 luckn ...
- TcpClient类与TcpListener类
TcpClient类 //构造方法1 TcpClient t = new TcpClient(); t.Connect(); //构造方法2 IPEndPoint iep = ); TcpClient ...
- MySQL好用的数学函数
最近项目很忙,分给我的功能都比较复杂,还好能应付的下来.在工作的过程中,我发现使用mysql的自带函数能够极大的减少程序的复杂度.这是必然的,使用mysql的函数,能够在程序里面省却很多的循环遍历.但 ...
- web前端开发修炼之道--编写高质量代码
想想自己的页面实现是否糟糕 Web标准--结构.样式和行为的分离 Web标准可分为三个部分:结构标准.样式标准.行为标准. 结构标准包括XML标准.XHTML标准.HTML标准 样式标准主要是指的CS ...
- 用GDB调试程序(一)
http://blog.csdn.net/haoel/article/details/2879 用GDB调试程序 GDB概述———— GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或 ...
- BZOJ1804: [Ioi2007]Flood 洪水
把点按坐标排序,每次找出最小的点,一定在最外层,再顺着把最外层的边删掉,经过了两次的边不会被冲毁. 其实不难写,但是写了很久. #include<bits/stdc++.h> #defin ...