Pregunta

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. 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(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. Thanks guys!

¿Fue útil?

Solución

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)

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.

Otros consejos

You can subclass ThreadPoolExecutor and include the re-submission logic there. It would be more elegant. ThreadPoolExecutor is well-designed and provides hook methods to do what you need. You would want to override ThreadPoolExecutor.afterExecute

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top