【问题标题】:Task execution with ExecutorService: Can I submit task within another task?使用 ExecutorService 执行任务:我可以在另一个任务中提交任务吗?
【发布时间】:2014-04-23 17:25:43
【问题描述】:

我想在现有任务中提交一个新任务以防失败(异常),但在运行以下代码时遇到了一些问题:

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) );
    }
    //...
}
//....

代码编译并运行几个步骤,然后抛出 java.util.concurrent.RejectedExecutionException。任何想法如何解释这一点以及如何解决?谢谢!

[编辑:下面添加的堆栈跟踪]


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)

[编辑:已解决]

原来我在 for 循环之后调用了 shutdown(),

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

所以新提交的任务被拒绝了。还了解到 ThreadPoolExecutor 是一个更好的选择。谢谢大家!

【问题讨论】:

  • 我无法重现这个。请发布完整的堆栈跟踪。
  • @SotiriosDelimanolis,已添加。
  • 你关闭了代码中未显示的池吗?
  • 这里运行没有问题。使用 java 8
  • @Raffaele,是的,我做到了。我在 for 循环之后调用了 shutdown()。一旦我删除它,异常就会消失。这有什么影响?

标签: java multithreading threadpool executorservice


【解决方案1】:

那个异常is thrown when a task is submitted and either

  • 执行器已关闭
  • 您超出了最大队列大小

没有看到代码我们无法判断,但很可能你在隐藏代码中做了这两件事之一(甚至可能在 main 中),你必须修复它(顺便说一句,可以使用 @ 自定义此行为987654322@)

我不知道这个问题是您的实际问题还是示例问题,但无论如何,我认为一个任务产生另一个任务不是常见的做法。你最好重构你的代码,让调用者自己在必要时提交一个新任务。并不是说它会解决您的问题,但肯定会改善您的程序设计。如果您描述了您的域,也许我们也可以提供帮助。

【讨论】:

  • 感谢@Raffaele,这是练习的示例代码。在未显示的代码中,我在 for 循环之后立即调用了 shutdown()。一旦我删除它,代码就可以毫无问题地运行。所以似乎在 ExecutorService 关闭后处理了异常--在所有任务完成后,shutdown() 是否预计有效?
  • @pdxhiker 来自 javadoc:shutdown() Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
【解决方案2】:

您可以继承ThreadPoolExecutor 并在其中包含重新提交逻辑。它会更优雅。 ThreadPoolExecutor 设计精良,提供钩子方法来做你需要的事情。你会想要覆盖ThreadPoolExecutor.afterExecute

【讨论】:

    猜你喜欢
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 2011-05-31
    • 1970-01-01
    相关资源
    最近更新 更多