我使用SWT打开主窗口然后应用程序启动,然后窗口通过静态函数运行任务非守护程序线程。现在,然后窗口关闭,整个应用程序终止,杀死未知状态的任务线程。它在Windows上运行,在Linux上运行时,线程在后台运行,检查自定义信号量并正确终止。 是否有理由和/或解决方法在Windows平台上达到相同的行为?
给出一个奇怪的代码示例:
package kg.clockworker;
public class Storage implements Runnable{
static int clockValue = 0;
@Override
public void run() {
for(clockValue=0; clockValue<1000; clockValue++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//ClockWorker.main(null);
Thread t = new Thread(new Storage());
//t.setDaemon(true);
t.start();
}
}
package kg.clockworker;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
public class ClockWorker extends Shell {
private Label label;
/**
* Launch the application.
* @param args
*/
public static void main(String args[]) {
Display display = Display.getDefault();
Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
public void run() {
try {
Display display = Display.getDefault();
ClockWorker shell = new ClockWorker(display);
shell.open();
shell.layout();
display.timerExec(40, new Runnable(){
@Override
public void run() {
shell.label.setText(Storage.clockValue+"");
display.timerExec(40, this);
}
});
Storage.main(null);
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the shell.
* @param display
*/
public ClockWorker(Display display) {
super(display, SWT.CLOSE | SWT.RESIZE | SWT.TITLE | SWT.APPLICATION_MODAL);
label = new Label(this, SWT.NONE);
label.setBounds(31, 20, 70, 20);
label.setText("0");
createContents();
}
/**
* Create contents of the shell.
*/
protected void createContents() {
setText("ClockWorker");
setSize(407, 132);
}
@Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
protected DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
//
return bindingContext;
}
}
在Linux上:然后关闭ClockWorker,应用程序仍在运行Storage。可以实现终止代码。 在Windows上:然后ClockWorker关闭,存储也关闭,可能处于未完成状态。
答案 0 :(得分:0)
您需要了解Realm.runWithDefault()
的作用;它会同步调用run()
的{{1}}方法,当Runnable
返回时,调用代码会继续。关键是您在主方法中调用了run()
,因此当Realm.runWithDefault()
返回时,它会继续在runWithDefault()
中继续,从而终止您的流程。
在您的main()
中,您正在执行典型的SWT事件循环(Runnable
),这会使readAndDispatch()
在Runnable
未被处置时保持不变,但是关闭SWT循环退出的Shell
后,您的Shell
方法结束(如上所述,然后将控制权返回run()
)。
我不确定为什么这会在Linux上有所不同,因为IIRC这些规则在任何JVM上都是相同的。在任何情况下,如果您希望在SWT shell关闭后继续进程,则需要添加一些逻辑来执行此操作;基本上在你拥有的两个线程之间进行协调。