私は次のことを達成したいと考えています: アプリケーションが起動すると、メイン スレッドはバックグラウンドで実行する必要がある 1 つ以上のワーカー スレッドを開始し、定期的に舞台裏で処理を行います。これらはメイン スレッドをブロックするべきではありません。
- メイン スレッドが終了します (通常のアプリケーション終了)。コマンド ライン ユーティリティの場合、これは
main(String[])
メソッドの最後に到達したときです。Swing GUI の場合は、ユーザーがFile >> Exit
メニューを選択したときなどです。 - オペレーティング システムが強制終了コマンド (SIGKILL など) をスローします。
- メインスレッドで予期せぬキャッチされていない例外が発生し、事実上それを強制終了します (これは上記の #1 の無礼なバージョンです)。
メインスレッドから開始/送信されたら、すべてのワーカースレッド ( Runnable
s) が本質的に独自のライフサイクルを持ち、メインスレッドとは独立して存在するようにします。しかし、いつでもメイン スレッドが停止した場合は、すべてのワーカーのシャットダウンが完了するまでメイン スレッドをブロックし (可能な場合)、メイン スレッドの停止を"許可" できるようにしたいと考えています。
これまでのところ私の最善の試みですが、あちこちでピースが欠けていることはわかっています:
public class MainDriver {
private BaneWorker baneWorker;
private ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
MainDriver driver = new MainDriver();
driver.run();
// We've now reached the end of the main method. All workers should block while they shutdown
// gracefully (if at all possible).
if(executor.awaitTermination(30, TimeUnit.SECONDS))
System.out.println("Shutting down...");
else {
System.out.println("Forcing shut down...");
executor.shutdownNow();
}
}
private void run() {
// Start all worker threads.
baneWorker = new BaneWorker(Thread.currentThread());
// More workers will be used once I get this simple example up and running...
executor.submit(baneWorker);
// Eventually submit the other workers here as well...
// Now start processing. If command-line utility, start doing whatever the utility
// needs to do. If Swing GUI, fire up a parent JFrame and draw the application to the
// screen for the user, etc.
doStuff();
}
private void doStuff() {
// ??? whatever
}
}
public class BaneWorker implements Runnable {
private Timer timer;
private TimerTask baneTask;
private Thread mainThread;
public BaneWorker(Thread mainThread) {
super();
this.mainThread = mainThread;
}
@Override
public void run() {
try {
timer = new Timer();
baneTask = new TimerTask() {
@Override
public void run() {
System.out.println("When the main thread is ashes...");
}
};
// Schedule the baneTask to kick off every minute starting now.
timer.scheduleAtFixedRate(baneTask, new Date(), 60 * 1000);
} catch(InterruptedException interrupt) {
// Should be thrown if main thread dies, terminates, throws an exception, etc.
// Should block main thread from finally terminating until we're done shutting down.
shutdown();
}
}
private void shutdown() {
baneTask.cancel();
System.out.println("...then you have my permission to die.");
try {
mainThread.join();
} catch(InterruptedException interrupt) {
interrupt.printStackTrace;
}
}
}
私はここで軌道に乗っていますか、それとも基地から外れていますか? これを必要な方法で機能させるには、何を変更する必要がありますか? 私は Java コンカレンシーを初めて使用し、コンカレンシー API を正しく使用するために最善を尽くしていますが、少しつまずきます。何か案は?前もって感謝します!