如何在不阻塞的情况下从 Executors 中捕获 RuntimeExceptions?
How to catch RuntimeExceptions from Executors without blocking?
我有一个接受新任务的执行程序服务:
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 1000; i++) {
try{
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(task);
}
catch (ExecutionException e) {
System.out.println(e.getMessage());
}
}
我的问题是我无法捕获 Runnable 抛出的任何异常,除非我这样做:
Future<?> future = executor.submit(task);
try {
future.get();
} catch (Exception e) {
System.out.println("############### exception :" + e.getMessage());
}
问题是 future.get() 是阻塞的,所以如果我不能 运行 我的任务是异步的,我的任务将不会 运行 并行,而是顺序.
我希望能够使用 Java 8 和 CompletableFuture 但我不能...
你还有别的想法吗?
谢谢
Runnable 中的代码在单独的线程上执行,因此您必须在 run()
方法中处理它的异常。
如果您需要收集所有异常以供以后处理,我会这样做:
ExecutorService executor = Executors.newFixedThreadPool(1000);
final List<Exception> exceptions = // a place to put exceptions
Collections.synchronizedList(new ArrayList<Exception>());
for (int i = 0; i < 1000; i++) {
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
exceptions.add(e); // save the exception for later
}
}
};
executor.submit(task);
}
// wait for all the tasks to finish, then...
for (Exception e: exceptions) {
// whatever you want to do
}
否则,如果您只想获取有关每个异常发生时的信息:
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
e.printStackTrace();
}
}
};
任何你需要在异步任务之后做的事情都可以添加到任务本身。
for (int i = 0; i < 1000; i++) {
final Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(new Runnable() {
public void run() {
try {
task.run();
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
或者您将它们组合成一个 Runnable。
这可能不是最好的解决方案,但我们可以创建一个 parent Runnable,它将完成实际 Runnable 的工作。 parent 将捕获您需要了解的所有异常。这是稍微复杂的方法:
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 5; i++) {
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
ParentRunnable t = new ParentRunnable();
t.setRunnable(task, i);
executor.submit(t);
}
}
static class ParentRunnable implements Runnable {
Runnable r;
int index;
public void setRunnable(Runnable r, int index){
this.r = r;
this.index = index;
}
public void run() {
try{
System.out.println("\n" + index + "\n");
r.run();
}catch(Exception e){
e.printStackTrace();
}
}
}
我有一个接受新任务的执行程序服务:
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 1000; i++) {
try{
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(task);
}
catch (ExecutionException e) {
System.out.println(e.getMessage());
}
}
我的问题是我无法捕获 Runnable 抛出的任何异常,除非我这样做:
Future<?> future = executor.submit(task);
try {
future.get();
} catch (Exception e) {
System.out.println("############### exception :" + e.getMessage());
}
问题是 future.get() 是阻塞的,所以如果我不能 运行 我的任务是异步的,我的任务将不会 运行 并行,而是顺序.
我希望能够使用 Java 8 和 CompletableFuture 但我不能... 你还有别的想法吗?
谢谢
Runnable 中的代码在单独的线程上执行,因此您必须在 run()
方法中处理它的异常。
如果您需要收集所有异常以供以后处理,我会这样做:
ExecutorService executor = Executors.newFixedThreadPool(1000);
final List<Exception> exceptions = // a place to put exceptions
Collections.synchronizedList(new ArrayList<Exception>());
for (int i = 0; i < 1000; i++) {
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
exceptions.add(e); // save the exception for later
}
}
};
executor.submit(task);
}
// wait for all the tasks to finish, then...
for (Exception e: exceptions) {
// whatever you want to do
}
否则,如果您只想获取有关每个异常发生时的信息:
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
e.printStackTrace();
}
}
};
任何你需要在异步任务之后做的事情都可以添加到任务本身。
for (int i = 0; i < 1000; i++) {
final Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(new Runnable() {
public void run() {
try {
task.run();
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
或者您将它们组合成一个 Runnable。
这可能不是最好的解决方案,但我们可以创建一个 parent Runnable,它将完成实际 Runnable 的工作。 parent 将捕获您需要了解的所有异常。这是稍微复杂的方法:
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 5; i++) {
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
ParentRunnable t = new ParentRunnable();
t.setRunnable(task, i);
executor.submit(t);
}
}
static class ParentRunnable implements Runnable {
Runnable r;
int index;
public void setRunnable(Runnable r, int index){
this.r = r;
this.index = index;
}
public void run() {
try{
System.out.println("\n" + index + "\n");
r.run();
}catch(Exception e){
e.printStackTrace();
}
}
}