swingWorker调用的synchronized方法中断了吗?
synchronized method called by swingWorker interrupted?
我有一个同步函数,它是从另一个函数的循环在新线程中启动的,并且有很多调用它。所以我有:
foo(){
new SwingWorker() {
@Override
public void doInBackground() {
sync_foo();
}
}.execute();
} catch (IOException e) {
log.error("", e);
}
}
sync_foo
定义为:
private synchronized void sync_foo() {
}
我在 sync_foo
中放置了一些调试行以检查它是否按预期工作。所以我有:
private synchronized void sync_foo() {
final Logger log = Logger.getLogger(getClass());
log.info("start");
...
log.info("finish");
}
这里的记录器是Log4J,据我所知确实是线程安全的。我注意到在日志文件中有时会有两个后续 "start"。所以我在末尾 log.info("still alive")
附近又加了一行,并让它越来越接近 log.info("start");
看看我是否停止获得双 starts
并且总是在 still alive
之间两个,但我还是明白了,最后我把它放在 log.info("start");
的下一行:
private synchronized void sync_foo() {
final Logger log = Logger.getLogger(getClass());
log.info("start");
log.info("still alive");
...
log.info("finish");
}
但时不时地,我仍然得到:
start
start
我觉得很费解。看来该方法以某种方式被打断了,但我不明白是如何打断的。我应该补充一点,sync_foo()
仅从 foo()
调用,我没有收到任何异常或任何类型的错误。
所以问题是:
一般情况下,方法被自己打断的可能原因有哪些?
我知道 Swing worker 可能有自己的处理线程执行的方法。我在上面使用的 SwingWorker 实际上已被覆盖,它的定义如 here 中所示。此扩展中是否有任何内容可能会错过相关异常?
同步依赖于共享锁,因此如果您看到多个线程调用并发同步的东西的行为,这意味着它们没有使用同一个锁。听起来 sync_foo 是在不同的对象上调用的。在方法上使用 synchronized
意味着对象实例上的监视器由想要进入该方法的线程获取,因此如果在不同的对象上调用该方法,则没有共享锁,也没有什么可以阻止线程进入一个对象上的方法,而另一个线程正在另一个对象上执行该方法。
你可以像这样创建一个 class 级别的锁:
public static final Object LOCK = new Object();
并将您的方法更改为
private void sync_foo() {
synchronized(LOCK) {
final Logger log = Logger.getLogger(getClass());
log.info("start");
log.info("still alive");
...
log.info("finish");
}
}
所以调用 sync_foo 的所有对象都将使用相同的锁,而不管它调用的是什么实例。
我有一个同步函数,它是从另一个函数的循环在新线程中启动的,并且有很多调用它。所以我有:
foo(){
new SwingWorker() {
@Override
public void doInBackground() {
sync_foo();
}
}.execute();
} catch (IOException e) {
log.error("", e);
}
}
sync_foo
定义为:
private synchronized void sync_foo() {
}
我在 sync_foo
中放置了一些调试行以检查它是否按预期工作。所以我有:
private synchronized void sync_foo() {
final Logger log = Logger.getLogger(getClass());
log.info("start");
...
log.info("finish");
}
这里的记录器是Log4J,据我所知确实是线程安全的。我注意到在日志文件中有时会有两个后续 "start"。所以我在末尾 log.info("still alive")
附近又加了一行,并让它越来越接近 log.info("start");
看看我是否停止获得双 starts
并且总是在 still alive
之间两个,但我还是明白了,最后我把它放在 log.info("start");
的下一行:
private synchronized void sync_foo() {
final Logger log = Logger.getLogger(getClass());
log.info("start");
log.info("still alive");
...
log.info("finish");
}
但时不时地,我仍然得到:
start
start
我觉得很费解。看来该方法以某种方式被打断了,但我不明白是如何打断的。我应该补充一点,sync_foo()
仅从 foo()
调用,我没有收到任何异常或任何类型的错误。
所以问题是:
一般情况下,方法被自己打断的可能原因有哪些?
我知道 Swing worker 可能有自己的处理线程执行的方法。我在上面使用的 SwingWorker 实际上已被覆盖,它的定义如 here 中所示。此扩展中是否有任何内容可能会错过相关异常?
同步依赖于共享锁,因此如果您看到多个线程调用并发同步的东西的行为,这意味着它们没有使用同一个锁。听起来 sync_foo 是在不同的对象上调用的。在方法上使用 synchronized
意味着对象实例上的监视器由想要进入该方法的线程获取,因此如果在不同的对象上调用该方法,则没有共享锁,也没有什么可以阻止线程进入一个对象上的方法,而另一个线程正在另一个对象上执行该方法。
你可以像这样创建一个 class 级别的锁:
public static final Object LOCK = new Object();
并将您的方法更改为
private void sync_foo() {
synchronized(LOCK) {
final Logger log = Logger.getLogger(getClass());
log.info("start");
log.info("still alive");
...
log.info("finish");
}
}
所以调用 sync_foo 的所有对象都将使用相同的锁,而不管它调用的是什么实例。