主Java线程终止时如何管理工作线程生命周期?
我想要实现以下功能:当我的应用程序启动时,主线程将启动1+个应该在后台运行的工作线程,并定期在幕后做些事情。 这些不应该阻止主线:一旦主要启动工人,它会继续做自己的事情,直到:
main(String[])
方法的末尾到达时; 在Swing GUI的情况下,当用户选择File >> Exit
菜单等时 一旦从主线程开始/提交,我希望所有工作线程( 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并发性,并且正在尽我所能正确使用Concurrency API,但却陷入了一丝困境。 有任何想法吗? 提前致谢!
主线程必须通知工作线程终止(通常这是通过使用标志来实现的),然后它应该在每个线程上调用join
以等待它们的终止。 看看这里:Java:如何使用Thread.join
你可以使用Runtime.addShutdownHook来注册一个未启动的线程,当一个JVM终止,系统关闭等等时,这个线程会被执行。这段代码可以自己做一些清理工作,或者通知运行的守护进程线程完成工作。 任何这样的清理代码都必须相对较快,因为在许多系统中,程序在被强制终止之前只有有限的时间进行清理。
也许你也可以考虑使你的后台线程守护进程线程。 然后,当main
完成并且在清理阶段仍然运行时,它们不会阻止JVM。
请注意,你不能拦截SIGKILL--这个信号被设计为不可避免的,直接的。 但它应该与SIGTERM,SIGHUP和类似的信号一起工作。
更新:您可以轻松创建运行守护程序线程的ExecutorService
。 所有你需要的是创建一个合适的ThreadFactory
:
public static class DaemonFactory
implements ThreadFactory
{
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
比你创建一个ExecutorService
好
public static void main(String argv[])
throws Exception
{
ExecutorService es
= Executors.newCachedThreadPool(new DaemonFactory());
// ^^^^^^^^^^^^^^^^^^^
es.submit(new Callable<Object>() {
public Object call() throws Exception {
Thread.sleep(100);
System.err.println("Daemon: " +
Thread.currentThread().isDaemon());
return null;
}
});
// Without this, JVM will terminate before the daemon thread prints the
// message, because JVM doesn't wait for daemon threads when
// terminating:
es.awaitTermination(3, TimeUnit.SECONDS);
}
关于Thread.join()
,您不应该尝试在由ExecutorService
管理的线程上使用它。 执行者负责管理他们。 你没有可靠的方法来枚举它的线程,执行程序可以根据它的配置创建和销毁线程等。唯一可靠的方法是调用shutdown();
然后awaitTermination(...);
。
如果SIGKILL是一个unix“kill -9”,那么你无能为力。
对于优雅的退出,请在你的主体中使用try / catch / finally。 catch
会捕获你的异常,并允许你做需要做的事情(recover?abort?) finally
会给你挂钩,让你的线程优雅地旋转下来。
快速查看你的代码,我没有看到你在跟踪你的线程实例的位置。 如果你打算告诉他们下台,你需要这些。
伪代码:
static Main(...) {
ArrayList threads = new ArrayList();
try {
for (each thread you want to spin up) {
threads.add(a new Thread())
}
}
catch { assuming all are fatal. }
finally {
for(each thread t in threads) {
t.shutdown();
t.join(); /* Be prepared to catch (and probably ignore) an exception on this, if shutdown() happens too fast! */
}
}
链接地址: http://www.djcxy.com/p/92045.html
上一篇: How to manage worker thread lifecycles when main Java thread terminates?
下一篇: Threading in Java