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 ...
随机推荐
- Lead推荐学asp.net书籍
ASP.NET 3.5 Unleashed 中文版: ASP.NET3.5揭秘(卷1) ASP.NET3.5揭秘(卷2) JS A Smarter Way to Learn JavaScript
- js-JavaScript高级程序设计学习笔记3
第五章 引用类型 1.使用new操作符和Date构造函数创建日期对象. 2.创建特定日期有两个方法--Date.parse()和Date.UTC().后者小时数为0时显示时间是8点,应该是因为本地是东 ...
- oracle 常用sql
-- 在sql中只有别名时用的是双引号select employee_id,last_name,12*salary as yearSalary from employees; select last_ ...
- Teamviewer11现在无法捕捉屏幕画面。这可能是由于快速的用户切换或远程桌面会话断开/最小化。
如果你用“远程桌面”连过去开启Teamviewer的话,当你退出“远程桌面”后,外网用Teamviewer连接就会出现这个问题. 解决方法: 不用远程连接过去开启Teamviewer,直接在在电脑本机 ...
- sersync2 安装,配置
介绍 rsync rsync,remote synchronize顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限.时间.软硬链接等附加信息.rsync是用 “ ...
- AngularJs ngHref、ngSrc、ngCopy/ngCut/ngPaste
ngHref 在Angular程序没完成改变链接上用{{hash}}方式绑定的href值的时候,当用户点击该链接会跳到一个错误的页面. 格式:ng-href=”value” value:表达式. 使用 ...
- iOS - Availability.h
>for 'dispatch' application inner to begin note `#include <Availability.h>` These macros ar ...
- ES6之let(理解闭包)和const命令
ES6之let(理解闭包)和const命令 最近做项目的过程中,使用到了ES6,因为之前很少接触,所以使用起来还不够熟悉.因此购买了阮一峰老师的ES6标准入门,在此感谢阮一峰老师的著作. 我们知道,E ...
- python 安装包总结
PIL安装(Centos6.6) 1. 安装PIL所需的系统库 (centos6.6)yum install zlib zlib-devel -yyum install libjpeg libjpeg ...
- JS-Array数组对象
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>A ...