我正在使用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());
}
}
}
您正在使用Display.asyncExec
将doSmth
调用都放入将在调用Display.readAndDispatch
后立即在UI线程中运行的可运行对象的列表。
因此,对doSmth
的第一个调用运行并进入同步块。
然后使用fork true调用pmd.run
。这将在单独的线程中运行可运行对象,并反复调用Display.readAndDispatch
以保持UI线程响应。
这些Display.readAndDispatch
调用将接听对doSmth
的第二个调用-但您仍在同步块内,并且仍在同一UI线程上,因此synchronized
不被阻塞,您将获得观察到的结果。
如果要在后台运行代码,请使用Job
并指定“计划规则”,以防止任何有冲突的第二作业同时运行。如果作业中有setUser(true)
,它将显示一个进度对话框。