简体   繁体   English

使用 ExecutorService 执行任务:我可以在另一个任务中提交任务吗?

[英]Task execution with ExecutorService: Can I submit task within another task?

I want to submit a new task within an existing task in case of a failure(Exception), but had some issues running the code below:我想在出现故障(异常)的情况下在现有任务中提交一个新任务,但在运行以下代码时遇到了一些问题:

public class TestTask implements Runnable{
private int myInt;
private ExecutorService exec;

public TestTask(int x, ExecutorService s){
    this.myInt=x;
    this.exec=s;
}

@Override
public void run() {         
    try{
        //print number if it's odd; otherwise throw exception
        if(this.myInt%2 ==0) throw new Exception();     
        else System.out.println("Asynchronous task: "+ this.myInt); //do sth

    } catch (Exception e) {
        System.out.println("resubmitting..");
        //## TODO: PROBLEM??
        this.exec.execute(new TestTask(this.myInt+1, this.exec));
    }
}

public static void main(String[] args) {
    int NTHREADS =2;
    final ExecutorService service= Executors.newFixedThreadPool(NTHREADS);
    //run tasks
    for(int i=0; i<10; i++){
        service.execute(new TestTask(i, service) );
    }
    //...
}
//....

The code compiles and runs for a few steps then throws java.util.concurrent.RejectedExecutionException .代码编译并运行几步,然后抛出java.util.concurrent.RejectedExecutionException Any ideas how to interpret this and how to fix?任何想法如何解释这个以及如何解决? Thanks!谢谢!

[EDIT: Stack Trace added below] [编辑:下面添加了堆栈跟踪]


resubmitting..
Asynchronous task: 1
resubmitting..
Asynchronous task: 3
resubmitting..
Asynchronous task: 5
resubmitting..
Exception in thread "pool-1-thread-2" java.util.concurrent.RejectedExecutionException: Task pe.ads.TestTask@4e19b97c rejected from java.util.concurrent.ThreadPoolExecutor@322ba3e4[Shutting down, pool size = 2, active threads = 2, queued tasks = 8, completed tasks = 3]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
    at pe.ads.TestTask.run(TestTask.java:26)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Exception in thread "pool-1-thread-1" java.util.concurrent.RejectedExecutionException: Task pe.ads.TestTask@31eb494e rejected from java.util.concurrent.ThreadPoolExecutor@322ba3e4[Shutting down, pool size = 2, active threads = 2, queued tasks = 8, completed tasks = 3]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
    at pe.ads.TestTask.run(TestTask.java:26)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Asynchronous task: 7Exception in thread "pool-1-thread-3" java.util.concurrent.RejectedExecutionException: Task pe.ads.TestTask@35afe17b rejected from java.util.concurrent.ThreadPoolExecutor@322ba3e4[Shutting down, pool size = 2, active threads = 2, queued tasks = 6, completed tasks = 6]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
    at pe.ads.TestTask.run(TestTask.java:26)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

resubmitting..
Asynchronous task: 9
Asynchronous task: 1
Exception in thread "pool-1-thread-5" java.util.concurrent.RejectedExecutionException: Task pe.ads.TestTask@53e64a3b rejected from java.util.concurrent.ThreadPoolExecutor@322ba3e4[Shutting down, pool size = 2, active threads = 2, queued tasks = 3, completed tasks = 8]
resubmitting..
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
    at pe.ads.TestTask.run(TestTask.java:26)
Asynchronous task: 1    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

[EDIT: Resolved] [编辑:已解决]

It turns out I called shutdown() right after the for loop,结果我在 for 循环之后立即调用了 shutdown(),

    for(int i=0; i<10; i++){
        service.execute(new TestTask(i, service) );
    }
    service.shutdown();

so new submitted tasks were rejected.所以新提交的任务被拒绝了。 Also learned that ThreadPoolExecutor is a better option.还了解到 ThreadPoolExecutor 是一个更好的选择。 Thanks guys!谢谢你们!

You can subclass ThreadPoolExecutor and include the re-submission logic there.您可以ThreadPoolExecutor并在其中包含重新提交逻辑。 It would be more elegant.会更优雅。 ThreadPoolExecutor is well-designed and provides hook methods to do what you need. ThreadPoolExecutor设计精良,并提供钩子方法来做你需要的。 You would want to override ThreadPoolExecutor.afterExecute你想覆盖ThreadPoolExecutor.afterExecute

That exception is thrown when a task is submitted and either : 提交任务时抛出该异常,并且

  • the executor has been shut down执行器已关闭
  • you exceeded the maximum queue size您超出了最大队列大小

We can't tell without seeing the code, but likely you do one of these two things in hidden code (maybe even in main ), and you have to fix it (btw, this behavior can be customized with setRejectedExecutionHandler )不看代码我们无法判断,但很可能您在隐藏代码中执行了这两件事之一(甚至可能在main ),并且您必须修复它(顺便说一句,此行为可以使用setRejectedExecutionHandler自定义)

I don't know if this question is your actual problem or a sample one, but anyway I don't think it's common practice for a task to spawn another task.我不知道这个问题是您的实际问题还是示例问题,但无论如何,我认为一个任务产生另一个任务并不是常见的做法。 You'd better restructure your code to make the caller itself submitting a new task when necessary.你最好重构你的代码,让调用者自己在必要时提交一个新任务。 Not that it will fix your problem, but will certainly improve the design of your program.并不是说它会解决您的问题,而是肯定会改进您的程序设计。 If you describe your domain, maybe we can help with that, too.如果您描述了您的域,也许我们也可以提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM