5

このような RejectedExecutionHandler と Runnable タスクを持つスレッドプールがあります。

sExecutorService = new ThreadPoolExecutor( ...    new MyRejectionHandler() );

interface MyTask extends Runnable { ... }

class MyTaskImpl implements MyTask { ...}     

私はこのようなタスクを実行します

   sExecutorService.submit(myTask);        

rejectExecution の場合、拒否された Runnable (つまり MyTask) を取得し、拒否されたものとしてマークするフィールドを設定することを望んでいました。しかし、それを MyTask にキャストできません。では、 rejectExecution に渡される runnable とは正確には何でしょうか? MyTask i submit ではないようです。RejectedExecutionHandler で拒否されたタスクを取得するにはどうすればよいですか。

public class MyRejectionHandler implements RejectedExecutionHandler{  
   public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor)  {
    MyTask myTask = (MyTask) runnable; // exception
    myTask.doSomething();
   }
java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to MyTask       
4

1 に答える 1

10

問題は、送信メソッドTreadPoolExecutor(実際にはAbstractExecutorService)を使用してタスクを送信すると、FutureTaskにラップされることです。その後、RunnableではなくFutureTaskを受け取ります。送信ではなく実行を呼び出すことができます。

sExecutorService.execute(yourTask);

FutureTaskからタスクを取得する方法はないと思います。runを呼び出すことしかできません。したがって、submitを呼び出したい場合で、runを呼び出す必要がある場合は、MyTaskに変換しないでください。

FutureTask myTask = (FutureTask) runnable;
myTask.run();
Object result = myTask.get();

MyTaskオブジェクトにアクセスする場合は、MyFutureTask extends FutureTaskを作成することもできます。これにより、オブジェクトを取得できます。

public MyFutureTask<V> extends FutureTask<V> {

    private Runnable myTask;

    public MyFutureTask(Runnable runnable, V result) {
        super(runnable, result);
        this.myTask = runnable;
    }

    public Runnable getMyTask() {
        return myTask;
    }        
}

また、ThreadPoolExecutorを拡張し、RunnableからFutureTaskへのラッピングを担当するnewTaskForメソッドを再定義する必要があります。

public class MyThreadPoolExecutor extends ThreadPoolExecutor {

    @Override
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new MyFutureTask(task, value);            
    }
}

その後、MyThreadPoolExecutorをThreadPoolExecutorとして使用し、タスク処理を拒否できます。

MyFutureTask myFutureTask = (MyFutureTask) runnable;
MyTask myTask = (MyTask) myFutureTask.getMyTask();
// Now you can do what you want with you task:
myTask.doSomthing();    
于 2012-06-07T12:23:59.500 に答える