在ThreadPoolExecutor中使用ExecutorService中的方法

方法invokeAny()和invokeAll()具有阻塞特性

方法invokeAny()取得第一个完成任务的结果值,当第一次任务执行完成后,会调用interrupt()方法将其他任务中断,所以在这些任务中可以结合if(Thread.currentThread().isInterrupted() == true)来决定任务是否继续运行。

  1. 无if(Thread.currentThread().isInterrupted() == true)代码:已经获得第一个运行的结果值后,其他线程继续运行。
  2. 有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 &lt; 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 &lt; 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 &lt; 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&lt;&gt;();
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 &lt; 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&lt;&gt;();
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的使用的更多相关文章

  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并发编程核心方法与框架-Future和Callable的使用

    Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值.但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get ...

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

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

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

    CyclicBarrier类似于CountDownLatch也是个计数器,不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了Cyc ...

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

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

随机推荐

  1. 【HDU 5750】Dertouzos(数学)

    题目给定n和d,都是10的9次方以内,求1到n里面有几个数最大因数是d?1000000组数据.解:求出d的满足p[i]*d<n的最小质因数是第几个质数.即为答案. #include<cst ...

  2. MyEclipse项目上有个感叹号

    如图: 然后把有叉的选项移除就可以了

  3. oracle配置数据库连接方式

    有以下两种: (1)tnsname.ora中添加信息 例如: (2)在plsq  database下添加地址 例如:192.168.1.210:1521/orcl

  4. [bzoj4408][Fjoi2016]神秘数

    Description 一个可重复数字集合$S$的神秘数定义为最小的不能被$S$的子集的和表示的正整数. 例如$S={1,1,1,4,13}$, $1=1$, $2=1+1$, $3=1+1+1$, ...

  5. shell !符号

    执行某历史命令 history找出历史命令id号 ! id

  6. jquery的$

    <!DOCTYPE HTML> <HTML> <head> <title>aa</title> <script type=" ...

  7. AC 自动机

    AC自动机(Aho-Corasick Automata)是经典的多模式匹配算法.从前我学过这个算法,但理解的不深刻,现在已经十分不明了了.现在发觉自己对大部分算法的掌握都有问题,决定重写一系列博客把学 ...

  8. .net数据库操作

    刚接触到数据库时总是被数据库中的一些基本概念,比如Connection.Command.DataReader等,给整的糊里糊涂.如今,对数据库的基本操作有了一定的认识,特此做出总结,以便后续工作中查阅 ...

  9. 第六次作业——利用MFC实现计算器图形界面以及简单四则运算表达式批处理

    参考资料:      1.MFC响应键盘      2.计算器实例      3.MFC文件对话框      4.MFCUpdateData()函数的使用      5.MFC教程      6.wi ...

  10. 对iOS中Delegate的理解

    首先 协议protocol 和委托delegate 是两个完全不同的概念  放在一起说 是因为我们总是在同一个头文件里看到它们: 首先解释一下什么是委托 :举个例子 ,我工作的时候给你打电话,让你帮我 ...