ExecutorService子线程返回值获取和exception捕获
来源:互联网 发布:刷视频点击率软件 编辑:程序博客网 时间:2024/06/05 04:55
最近在项目中需要使用多线程的并发来处理数据,刚开始希望使用static关键字来控制总的请求数,通过加减计数来进行数据请求的调度,本来并发量就不是很高,可是在实际的实验环境中,因为不能很好的控制请求的先后顺序,达到FIFO的要求,所以准备改善优化一下。对于线程池的使用不是很熟悉,通过网上的一些实例,结合自己的实际需求,对现成的一个实例,进行了优化,希望给各位有新的启发。
根据需求,主要做两方面的改正:
1.要对子线程的结果进行判断,这要求ExecutorService的执行结果必须有返回值
2.要捕获子线程的自定义异常。
首先第1点,获取任务的执行的返回值。
ExecutorService能够执行的任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。两者都可以被ExecutorService执行,但是Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的(<T> task) 方法来执行,并且返回一个<T><T>,是表示任务等待完成的 Future。故此选定实现接口为callable。
import java.util.Random;
import java.util.concurrent.Callable;
public class TaskWithResult implements Callable<String> {
private int id;
private static final String RESULT_NG_39 = "39";
public TaskWithResult(int id) {
this.id = id;
}
/**
* 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
*
* @return
* @throws Exception
*/
public String call() throws TaskException {
System.out.println("call()方法被自动调用,干活!!! "
+ Thread.currentThread().getName());
if (new Random().nextBoolean())
// 此处为自定义的exception, 包含返回的error code,在实际的开发中,不同的错误会对应不同的code
throw new TaskException("Meet error in task."
+ Thread.currentThread().getName(), RESULT_NG_39);
// 一个模拟耗时的操作
for (int i = 999999999; i > 0; i--)
;
// return "OK";
return "call()方法被自动调用,任务的结果是:" + id + " "
+ Thread.currentThread().getName();
}
}
第二.要捕获子线程的自定义异常。
这个是很关键的一环,项目开发中会有各种类型的异常,各种不同的message,errorcode,能够分门别类的正确区分抛出,对以后维护调试起到事半功倍的作用。
自定义的异常类:
package threatPool;
public class TaskException extends Exception {
/**
*
*/
private static final long serialVersionUID = 11583612349862927L;
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
private String errorCode;
// 主要是希望通过errorCode的不同,区分不同业务段的不同error
public TaskException(String message, String errorCode) {
super(message);
setErrorCode(errorCode);
}
}
最后,main函数调用:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorServiceTest {
private static final String RESULT_NG_39 = "39";
public static void main(String[] args) throws TaskException {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 创建10个任务并执行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
TaskWithResult tr = new TaskWithResult(i);
// 使用的submit,非excute方法
Future<String> future = executorService.submit(tr);
// 将任务执行结果存储到List中
resultList.add(future);
}
executorService.shutdown();
// 遍历任务的结果
for (Future<String> fs : resultList) {
try {
// 打印各个线程(任务)执行的结果
System.out.println(fs.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
// 获得子线程中抛出的异常code,注意此时使用的e.getCause(),对象的转型使用,我们在
// 实际项目中不是简简单单的获得这个exception打印出来,而是通过这个exception获得更多的信息
String errorCode = ((TaskException) e.getCause())
.getErrorCode();
if(RESULT_NG_39.equals(errorCode)){
// log.info("XXXXXXXXXXXXXXXX");
}
// e.printStackTrace();
return;
}
}
}
}
执行结果:
call()方法被自动调用,干活!!! pool-1-thread-1
call()方法被自动调用,干活!!! pool-1-thread-2
call()方法被自动调用,干活!!! pool-1-thread-3
call()方法被自动调用,干活!!! pool-1-thread-5
call()方法被自动调用,干活!!! pool-1-thread-4
call()方法被自动调用,干活!!! pool-1-thread-6
call()方法被自动调用,干活!!! pool-1-thread-7
call()方法被自动调用,干活!!! pool-1-thread-8
call()方法被自动调用,干活!!! pool-1-thread-10
call()方法被自动调用,干活!!! pool-1-thread-9
call()方法被自动调用,任务的结果是:0 pool-1-thread-1
call()方法被自动调用,任务的结果是:1 pool-1-thread-2
the error code is 39 !
the error code is 39 !
call()方法被自动调用,任务的结果是:4 pool-1-thread-5
call()方法被自动调用,任务的结果是:5 pool-1-thread-6
call()方法被自动调用,任务的结果是:6 pool-1-thread-7
the error code is 39 !
call()方法被自动调用,任务的结果是:8 pool-1-thread-9
call()方法被自动调用,任务的结果是:9 pool-1-thread-10
感谢各位前人的demo,也希望给大家一些启示。
- ExecutorService子线程返回值获取和exception捕获
- 使用callable获取子线程的返回值
- 从子线程返回值
- 线程池ExecutorService和BlockingQueue
- Java Exception 捕获和展示
- Java Exception 捕获和展示
- Java Exception 捕获和展示
- Java Exception 捕获和展示
- Java Exception 捕获和展示
- 如何捕获子线程异常
- 获取线程池的方法 ExecutorService
- Callable 获取线程返回值
- FutureTask获取线程返回值
- 在一个有返回值的方法里使用了子线程,如何返回子线程中的值,如下代码中,我在子线程获取到了address的值,但是这个方法的返回结果是空,该如何解决?
- 异步接收子线程的返回值
- python获得子线程的返回值
- python获得子线程的返回值
- Linux 获取子进程的返回值
- GR冻结库存计算函数
- 对话框菜单不响应UPDATE_COMMAND_UI
- 2013年托福听力精选短语
- IIS下PHP的ISAPI和FastCGI比较
- 安装SQl 2008为SQL Server代理服务提供的凭据无效
- ExecutorService子线程返回值获取和exception捕获
- wpa_supplicant与kernel的接口
- range断点续传
- USB 驱动程序
- 最长回文串长度——manacher算法
- 一些有用的dll
- hbase-0.94.16搭建eclipse源代码工程
- Android SDK. HTTP POST double variable
- C++ 引用与指针