我在我的应用程序中使用多个线程。基本上我有一个组合框,当选择收件箱时,p1恢复,p2暂停,选择发送后,p2开始,p1停止。下面是代码(我确定它并不完美)
public void modifyText(ModifyEvent e) {
if (combo.getText().equals("Inbox"))
{
synchronized(p2)
{
p2.cont = false;
}
table.removeAll();
synchronized(p1)
{
p1.cont = true;
p1.notify();
}
}
else if (combo.getText().equals("Sent"))
{
synchronized(p2)
{
p1.cont = false;
}
table.removeAll();
synchronized(p1)
{
p2.cont = true;
p2.notify();
}
}
}
});
对于P1和P2我在他们的while循环中有这个:
synchronized (this) {
while (cont == false)
try {
wait();
} catch (Exception e) {
}
}
......因为它现在正在工作(我是线程的初学者)。在组合框中按下Sent后,我收到IllegalStateMonitorException。任何人都可以帮我解决问题吗?
谢谢和问候, Krt_Malta
答案 0 :(得分:6)
问题在于:
synchronized(p1)
{
p2.cont = true;
p2.notify();
}
当你没有锁定p2.notify()
时,你正在进行p2
(你必须握住显示器来调用通知)。将synchronized(p1)
更改为synchronized(p2)
。此外,您还需要反转其他同步子句,这也是错误的。所以,作为一个例子:
synchronized(p1)
{
p1.cont = false;
// p1.notify(); <- do you need this here?
}
table.removeAll();
synchronized(p2)
{
p2.cont = true;
p2.notify();
}
另外,你的其他代码也有点不对,锁定整个循环是非常糟糕的做法,使它更具原子性。
while (!cont) {
synchronized (this) {
try {
wait();
} catch (Exception e) {
}
}
}
其他优化,如果可能,请避免synchronised
:
if (p1.cont) {
synchronized(p1)
{
p1.cont = false;
// p1.notify(); <- do you need this here?
}
}
table.removeAll();
if (!p2.cont) {
synchronized(p2)
{
p2.cont = true;
p2.notify();
}
}
在此处创建cont字段volatile
,并根据需要镜像if语句的其他部分。
编辑:回顾这个并与我最近面临的并发错误作斗争,任何实现此模式的人都可能面临无限等待的问题,如果一个对象被锁定&amp;正在通过while循环的条件查看半锁定(这是因为在评估条件和强制等待语句之间状态可以改变的间隙)。在这种情况下,将同步块放在循环的外部上。
答案 1 :(得分:0)
在此代码中
synchronized(p1)
{
p2.cont = true;
p2.notify();
}
您正在p1
进行同步,但在notify()
上调用p2
,这会导致异常。
答案 2 :(得分:-1)
您不能在awt事件调度线程中等待,否则会占用整个应用程序。阅读http://en.wikipedia.org/wiki/Event_dispatching_thread
除非你真的知道自己在做什么,否则你不应该使用原始线程。查看http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html并阅读Executors