在同步块中使用分叉的ProgressMonitorDialog

问题描述 投票:0回答:1

我正在使用jface ProgressMonitorDialog来缓存一些数据。这是在同步块中完成的,以免遇到并发问题。

但是奇怪的是,如果我使用参数fork = true调用ProgressMonitorDialog#run,则同步块不起作用。

有人可以向我解释这里发生了什么吗?

输出:

start synchronization Thread[main,5,main]
start synchronization Thread[main,5,main]
finished synchronization Thread[main,5,main]
finished synchronization Thread[main,5,main]

代码:

    private void test() {
        Shell shell = new Shell();
        SyncTest st = new SyncTest(shell);

        shell.getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
                st.doSmth();
            }
        });
        shell.getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
                st.doSmth();
            }
        });
    }

    private static class SyncTest {
        private static final Object LOCK = new Object();

        private Shell shell;

        public SyncTest(Shell shell) {
            this.shell = shell;
        }

        public void doSmth() {
            synchronized (LOCK) {
                System.out.println("start synchronization " + Thread.currentThread().toString());
                try {
                    ProgressMonitorDialog pmd = new ProgressMonitorDialog(shell);
                    pmd.run(true, true, new IRunnableWithProgress() {
                        @Override
                        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                            Thread.sleep(1000);
                        }
                    });
                } catch (InvocationTargetException | InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("finished synchronization " + Thread.currentThread().toString());
            }
        }
    }
synchronization jface
1个回答
0
投票

您正在使用Display.asyncExecdoSmth调用都放入将在调用Display.readAndDispatch后立即在UI线程中运行的可运行对象的列表。

因此,对doSmth的第一个调用运行并进入同步块。

然后使用fork true调用pmd.run。这将在单独的线程中运行可运行对象,并反复调用Display.readAndDispatch以保持UI线程响应。

这些Display.readAndDispatch调用将接听对doSmth的第二个调用-但您仍在同步块内,并且仍在同一UI线程上,因此synchronized不被阻塞,您将获得观察到的结果。

如果要在后台运行代码,请使用Job并指定“计划规则”,以防止任何有冲突的第二作业同时运行。如果作业中有setUser(true),它将显示一个进度对话框。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.