在同步块中使用分叉的 ProgressMonitorDialog
Using forked ProgressMonitorDialog in synchronized block
我正在使用 jface ProgressMonitorDialog 来缓存一些数据。这是在同步块中完成的,以避免 运行 出现并发问题。
但奇怪的是,如果我使用参数 fork=true 调用 ProgressMonitorDialog#运行,同步块将不起作用。
谁能给我解释一下这是怎么回事?
输出:
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
调用都放入将在 UI 线程中 运行 的 运行 功能列表一旦 Display.readAndDispatch
被调用。
所以第一个调用doSmth
运行s就进入了synchronized块。
然后调用 pmd.run
fork true。此 运行 在单独的线程中启用 运行 并且还重复调用 Display.readAndDispatch
以保持 UI 线程响应。
这些 Display.readAndDispatch
调用将接收对 doSmth
的第二次调用 - 但您仍在同步块内并且仍在同一个 UI 线程上,因此 synchronized
不会阻塞,您会得到观察到的结果。
如果您想 运行 在后台使用代码,请使用 Job
并指定 'scheduling rule' 以防止同时从 运行ning 产生任何冲突的第二个作业.如果作业中有 setUser(true)
,它将显示一个进度对话框。
我正在使用 jface ProgressMonitorDialog 来缓存一些数据。这是在同步块中完成的,以避免 运行 出现并发问题。
但奇怪的是,如果我使用参数 fork=true 调用 ProgressMonitorDialog#运行,同步块将不起作用。
谁能给我解释一下这是怎么回事?
输出:
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
调用都放入将在 UI 线程中 运行 的 运行 功能列表一旦 Display.readAndDispatch
被调用。
所以第一个调用doSmth
运行s就进入了synchronized块。
然后调用 pmd.run
fork true。此 运行 在单独的线程中启用 运行 并且还重复调用 Display.readAndDispatch
以保持 UI 线程响应。
这些 Display.readAndDispatch
调用将接收对 doSmth
的第二次调用 - 但您仍在同步块内并且仍在同一个 UI 线程上,因此 synchronized
不会阻塞,您会得到观察到的结果。
如果您想 运行 在后台使用代码,请使用 Job
并指定 'scheduling rule' 以防止同时从 运行ning 产生任何冲突的第二个作业.如果作业中有 setUser(true)
,它将显示一个进度对话框。