Java完成工作单元,直到发出停止信号
我有一些(Linux)C代码,我正在将其转换为Java。该代码有一个主循环,用于在每个环上检查来自操作系统的术语信号,否则会阻塞信号。这是因为它在循环中所做的每一个“功单元”都是完全完成的(不会被中间的信号中断) 事实证明,用Java实现这一点有些“有趣”。我已经提出了一些测试代码(如下所示),这些代码似乎有效,但我不确定它是否会一直有效,或者我是否只是在测试中“幸运” 所以,这就是我的问题:这是一个好的代码,还是只是偶尔能工作的代码? TL;DR:工作线程和关闭线程调用一个公共的同步方法Java完成工作单元,直到发出停止信号,java,signals,synchronized,atomicity,shutdown-hook,Java,Signals,Synchronized,Atomicity,Shutdown Hook,我有一些(Linux)C代码,我正在将其转换为Java。该代码有一个主循环,用于在每个环上检查来自操作系统的术语信号,否则会阻塞信号。这是因为它在循环中所做的每一个“功单元”都是完全完成的(不会被中间的信号中断) 事实证明,用Java实现这一点有些“有趣”。我已经提出了一些测试代码(如下所示),这些代码似乎有效,但我不确定它是否会一直有效,或者我是否只是在测试中“幸运” 所以,这就是我的问题:这是一个好的代码,还是只是偶尔能工作的代码? TL;DR:工作线程和关闭线程调用一个公共的同步方法 只要
只要关闭钩子在您期望的所有情况下都运行(并完成),它就一定是好的。根据SIGTERM,它似乎与预期一样工作。如果您不需要使用信号处理程序显式捕获操作系统信号,我认为您不必担心。所有可用的证据表明,如果您注册了一个ShutdownHook,那么它将在一个TERM或INT信号传递到JVM时启动,所有其他线程都将保持独立,直到ShutdownHook运行()方法退出(当任何仍在运行的方法将被终止时) 因此,这导致了一个更简单的解决方案,它避免了同步:
public class AnotherTestShutdownHook {
static int a = 0; /* should end up 0 */
static boolean go = true; /* signaled to stop */
static Thread mainThread = Thread.currentThread();
private static void trySleep ( int msecs ) {
try { Thread.sleep(msecs); } catch (InterruptedException e) {}
}
private static void tryJoin ( Thread t ) {
try { t.join(); } catch (InterruptedException e) {}
}
/*
* this simulates a process that we want to do completely
* or not at all.
*/
private static void doitall () {
System.out.println("start");
++a;
trySleep(5000);
System.out.println("end");
--a;
}
/*
* starts a thread to wait for a shutdown signal,
* then does units of work until told to stop
*/
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Shutdown coming...");
go = false;
tryJoin(mainThread); // wait for mainThread to exit
System.out.println("Shutdown hook! " + a);
}
});
while (go) {
doitall();
}
System.out.println("goodbye");
}
}
为什么你认为它不会每次都起作用?我没有发现任何缺陷,在一个退出信号上,如果JVM正常关闭或使用^C关闭,doitall()的工作应该完成。我想你已经阅读了Java文档。我在谷歌上搜索了很多,我找到了很多关于JNI和sun.misc.motled.carbody的话题,“你没有用Java的方式思考”等等,但我没有找到这种方法,所以我有点自我怀疑。谢谢你鼓励我重读这个问题——我认为这是最有用的答案——他想打断所有其他的线索,但这只是一个小小的飞跃,让它们很好地结束。
public class AnotherTestShutdownHook {
static int a = 0; /* should end up 0 */
static boolean go = true; /* signaled to stop */
static Thread mainThread = Thread.currentThread();
private static void trySleep ( int msecs ) {
try { Thread.sleep(msecs); } catch (InterruptedException e) {}
}
private static void tryJoin ( Thread t ) {
try { t.join(); } catch (InterruptedException e) {}
}
/*
* this simulates a process that we want to do completely
* or not at all.
*/
private static void doitall () {
System.out.println("start");
++a;
trySleep(5000);
System.out.println("end");
--a;
}
/*
* starts a thread to wait for a shutdown signal,
* then does units of work until told to stop
*/
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Shutdown coming...");
go = false;
tryJoin(mainThread); // wait for mainThread to exit
System.out.println("Shutdown hook! " + a);
}
});
while (go) {
doitall();
}
System.out.println("goodbye");
}
}