簡體   English   中英

使用 ExecutorService 執行任務:我可以在另一個任務中提交任務嗎?

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

我想在出現故障(異常)的情況下在現有任務中提交一個新任務,但在運行以下代碼時遇到了一些問題:

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 是一個更好的選擇。 謝謝你們!

您可以ThreadPoolExecutor並在其中包含重新提交邏輯。 會更優雅。 ThreadPoolExecutor設計精良,並提供鈎子方法來做你需要的。 你想覆蓋ThreadPoolExecutor.afterExecute

提交任務時拋出該異常,並且

  • 執行器已關閉
  • 您超出了最大隊列大小

不看代碼我們無法判斷,但很可能您在隱藏代碼中執行了這兩件事之一(甚至可能在main ),並且您必須修復它(順便說一句,此行為可以使用setRejectedExecutionHandler自定義)

我不知道這個問題是您的實際問題還是示例問題,但無論如何,我認為一個任務產生另一個任務並不是常見的做法。 你最好重構你的代碼,讓調用者自己在必要時提交一個新任務。 並不是說它會解決您的問題,而是肯定會改進您的程序設計。 如果您描述了您的域,也許我們也可以提供幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM