为什么非守护程序线程被终止然后所有SWT GUI线程在Windows上关闭?

时间:2014-12-23 16:48:44

标签: java linux eclipse multithreading swt

我使用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关闭,存储也关闭,可能处于未完成状态。

1 个答案:

答案 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关闭后继续进程,则需要添加一些逻辑来执行此操作;基本上在你拥有的两个线程之间进行协调。

相关问题