我想实现以下目标:当我的应用程序启动时,主线程将启动 1+ 个应该在后台运行的工作线程,并定期在后台做一些事情。这些不应该阻塞主线程:一旦 main 启动了工作线程,它会继续做自己的事情,直到:
- 主线程结束(正常的应用程序终止)——在命令行实用程序的情况下,这
main(String[])
是到达方法结束的时间;在 Swing GUI 的情况下,可能是当用户选择File >> Exit
菜单等时。 - 操作系统抛出kill命令(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,但有点磕磕绊绊。有任何想法吗?提前致谢!