Java线程问题

发布于 2024-08-25 22:53:00 字数 1362 浏览 6 评论 0原文

我在我的应用程序中使用多个线程。基本上我有一个组合框,选择收件箱后,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) {
                }
        } 

... 现在它正在工作(我是线程的初学者)。在组合框中按“发送”后,我收到 IllegalStateMonitorException。任何人都可以帮我解决这个问题吗?

谢谢和问候, Krt_马耳他

I'm using multiple threads in my application. Basically I have a combo box and upon selecting Inbox, p1 resumes and p2 is suspended and upon selecting Send, p2 starts and p1 stops. Below is the code (I'm sure it's not perfect)

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();
                    }
                }
            }
        });

and for P1 and P2 I have this inside their while loops:

synchronized (this) {
            while (cont == false)
                try {
                    wait();
                } catch (Exception e) {
                }
        } 

... As it is it's now working (I'm a beginner to threads). On pressing Sent in the combo box, I get an IllegalStateMonitorException. Could anyone help me solve the problem plz?

Thanks and regards,
Krt_Malta

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾城月光淡如水﹏ 2024-09-01 22:53:00

问题就在这里:

synchronized(p1)
{
    p2.cont = true;
    p2.notify();
}

当您没有锁定 p2 时,您正在执行 p2.notify() (您必须持有监视器才能对其调用通知)。将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) {
       }
    }
}

其他优化,如果可能,请避免同步:

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 字段设置为易失性,并根据需要镜像 if 语句的其他部分。

编辑:回顾这一点并与我最近面临的并发错误作斗争,任何实现此模式的人都可能面临无限等待的问题,如果一个对象被锁定并且被锁定。 half-locked on 由 while 循环的条件来查看(这是因为在评估条件和施加 wait 语句之间存在状态可以改变的间隙)。在这种情况下,请将同步块放在循环的外部

the problem is here:

synchronized(p1)
{
    p2.cont = true;
    p2.notify();
}

You are doing p2.notify() when you haven't got a lock on p2 (you must hold the monitor to call notify on it). Change synchronized(p1) to synchronized(p2). Additionally, you need to reverse the other synchronized clause as well which is also faulty. So, as an example:

synchronized(p1) 
{
    p1.cont = false;
    // p1.notify(); <- do you need this here?
}
table.removeAll();
synchronized(p2)
{
    p2.cont = true;
    p2.notify();
}

Additionally, your other code is a bit wrong too, it's very bad practice to lock inside an entire loop, make it a bit more atomic.

while (!cont) {
    synchronized (this) {
       try {
           wait();
       } catch (Exception e) {
       }
    }
}

Additional optimisation, avoid synchronised if possible:

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();
   }
}

Make the cont field volatile here, and mirror for the other part of the if statement as appropriate.

Edit: looking back on this and battling with a concurrency bug I was recently facing, anyone implementing this pattern might face a problem with an infinite wait, if an object being locked & half-locked on is being looked at by the conditional of the while loop (this is because there is a gap where the state can change between evaluating the conditional and the imposition of the wait statement). In this case, place the synchronized block on the outside of the loop.

女皇必胜 2024-09-01 22:53:00

在此代码中,

                synchronized(p1)
                {
                    p2.cont = true;
                    p2.notify();
                }

您在 p1 上进行同步,但在 p2 上调用 notify(),这会导致异常。

In this code

                synchronized(p1)
                {
                    p2.cont = true;
                    p2.notify();
                }

You're synchronizing on p1 but calling notify() on p2, which leads to the exception.

怪我太投入 2024-09-01 22:53:00

您不能在 awt 事件调度线程中等待,否则会占用您的整个应用程序。阅读http://en.wikipedia.org/wiki/Event_dispatching_thread

另外你不应该使用原始线程,除非您真的知道自己在做什么。查看 http://java. sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html 并阅读 执行器

You can't wait in awt event dispatch thread or else that will hold up your entire app. Read about http://en.wikipedia.org/wiki/Event_dispatching_thread

Also you shouldn't use raw threads unless you really know what you are doing. Check out http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html and read up on Executors

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文