割り込み可能なタスクのタイムアウトを備えた ExecutorService
タスクを同時に実行する場合、多くの場合、指定された時間を超えるタスクを適切に中断するメカニズムを持つことが望ましいです。タイムアウト。これは、長時間実行されるタスクがアプリケーションのロックアップやパフォーマンスの問題を引き起こす可能性がある状況で特に役立ちます。
TimeoutExecutorService の実装
ここでは、TimeoutThreadPoolExecutor の実装を拡張して、標準の ThreadPoolExecutor とタイムアウトを組み込む機能:
class TimeoutThreadPoolExecutor extends ThreadPoolExecutor { private final long timeout; private final TimeUnit timeoutUnit; private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor(); private final ConcurrentMap<Runnable, ScheduledFuture> runningTasks = new ConcurrentHashMap<>(); public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, long timeout, TimeUnit timeoutUnit) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); this.timeout = timeout; this.timeoutUnit = timeoutUnit; } // Override methods to implement timeout behavior @Override protected void beforeExecute(Thread t, Runnable r) { if (timeout > 0) { ScheduledFuture scheduled = timeoutExecutor.schedule(new TimeoutTask(t), timeout, timeoutUnit); runningTasks.put(r, scheduled); } } @Override protected void afterExecute(Runnable r, Throwable t) { ScheduledFuture timeoutTask = runningTasks.remove(r); if (timeoutTask != null) { timeoutTask.cancel(false); } } // Timeout task to interrupt threads class TimeoutTask implements Runnable { private final Thread thread; public TimeoutTask(Thread thread) { this.thread = thread; } @Override public void run() { thread.interrupt(); } } }
使用法:
TimeoutThreadPoolExecutor を使用するには、タイムアウト値を指定してインスタンス化するだけです:
TimeoutThreadPoolExecutor executor = new TimeoutThreadPoolExecutor( 4, // corePoolSize 8, // maximumPoolSize 1, // keepAliveTime TimeUnit.SECONDS, // timeUnit new LinkedBlockingQueue<>(), // workQueue 5, // timeout TimeUnit.SECONDS // timeoutUnit );
次に、タスクを実行者に次のように送信します。通常:
executor.submit(() -> { // long-running task });
タスクが指定されたタイムアウトよりも長くかかる場合、タスクを実行しているスレッドが中断され、タスクが正常に終了します。
代替解決策
タスクのタイムアウトを実装するもう 1 つの方法は、「」で提案されているように、ScheduledExecutorService を使用することです。 応答。これには、タスクを Callable として送信し、作成された Future を保持することが含まれます。その後、一定期間後に将来のタスクをキャンセルするように 2 番目のタスクをスケジュールし、事実上タスクを中断できます。
以上がExecutorService で中断可能なタスクのタイムアウトを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。