gpt4 book ai didi

java - 如果线程列表中的任何线程发生异常,则中断所有线程

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:38:16 24 4
gpt4 key购买 nike

我正在使用 invokeAll() 调用线程列表。 AFAIK invokeAll() 将仅在所有线程完成其任务时返回。

ExecutorService threadExecutor = Executors.newFixedThreadPool(getThreadSize());
List<Future<Object>> future = w_threadExecutor.invokeAll(threadList);

当所有线程结束时调用

for (Future<Object> w_inProgressThread : w_future)
{
//

它停止发生异常的线程,而不是其余线程。如果任何线程抛出异常,有没有办法停止所有其他线程?还是我必须提交每个任务而不是 invokeAll()??

我尝试在 invokeAll() 上使用 invokeAny() 而不是 invokeAll() 但没有取消剩余的任务invokeAny() :如果其中一个任务完成(或抛出异常),则 Callable 的其余部分将被取消。引用:http://tutorials.jenkov.com/java-util-concurrent/executorservice.html

更新:

CompletionService<Object> completionService = new ExecutorCompletionService<Object>(w_threadExecutor);
List<Future<Object>> futures = new ArrayList<Future<Object>>();
for(Thread w_mt : threadList)
{
futures.add(completionService.submit(w_mt));
}
for (int numTaken = 0; numTaken < futures.size(); numTaken++) {
Future f = completionService.take();
try {
Object result = f.get();
System.out.println(result); // do something with the normal result
} catch (Exception e) {
System.out.println("Catched ExecutionException, shutdown now!");
//threadExecutor.shutdownNow();
Thread.currentThread().interrupt();

for (Future<Object> inProgressThread : futures)
{
inProgressThread.cancel(true);
}
break;
}

更新 1:

按照waltersu的建议我试过了

ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
CompletionService<Object> completionService = new ExecutorCompletionService<Object>(threadExecutor);
List<Future<Object>> futures = new ArrayList<Future<Object>>();
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
String s=null;
// Thread.sleep(1000);
for(int i=0; i < 1000000; i++){
int j =10 ;
if(i==100)
{

s.toString();
}

System.out.println("dazfczdsa :: " + i);
}
//throw new Exception("This is an expected Exception");
return s;
}
}));
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
for(int i=0; i < 1000000; i++){
int j =0 ;
j= j+2;
System.out.println("dasa :: " + i);
}
Thread.sleep(3000);

return "My First Result";
}
}));

while (futures.size() > 0) {
Future f = completionService.take();
futures.remove(f);
try {
Object result = f.get();
System.out.println(result); // do something with the normal result
} catch (ExecutionException e) {
System.out.println("Caught exception from one task: " + e.getCause().getMessage() + ". shutdown now!");
f.cancel(true);
threadExecutor.shutdownNow();
break;
}
}
System.out.println("Main exists");

异常发生时不会停止

最佳答案

你必须一个一个地submit(),而不是invokeAll(),然后检查Future是否有Exception。

public static void main(String[] args) throws InterruptedException {
ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
CompletionService<Object> completionService = new ExecutorCompletionService<>(threadExecutor);
List<Future<Object>> futures = new ArrayList<>();
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Thread.sleep(1000);
throw new Exception("This is an expected Exception");
}
}));
futures.add(completionService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Thread.sleep(3000);
return "My First Result";
}
}));

while (futures.size() > 0) {
Future f = completionService.take();
futures.remove(f);
try {
Object result = f.get();
System.out.println(result); // do something with the normal result
} catch (ExecutionException e) {
System.out.println("Caught exception from one task: " + e.getCause().getMessage() + ". shutdown now!");
threadExecutor.shutdownNow();
break;
}
}
System.out.println("Main exists");
}

更新 1:(回答 op 的更新 1 问题)

那是因为你的任务有一个长循环,它不检查中断,这使得你的任务不可取消。那你怎么阻止它?我认为您必须修改其他任务以使其可取消。作为the official doc说:

What if a thread goes a long time without invoking a method that throws InterruptedException? Then it must periodically invoke Thread.interrupted, which returns true if an interrupt has been received. For example:

for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}

如果你不想修改你的任务又想让它快速停止怎么办?有一种方法可以停止不可取消的线程。它是 Thread.stop()。但是,起初,如果不使用反射,就无法从线程池中获取线程。此外,根据 javadoc,它已被弃用,因为“它本质上是不安全的” .

因此,最好的做法(我认为)是检查任务(或部分代码)中的中断,这些中断既不可取消又需要很长时间才能完成。

关于java - 如果线程列表中的任何线程发生异常,则中断所有线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37879274/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com