所以我有一个程序通过使用2个线程打印Hello和Goodbye。 我需要100次打印Hello和Goodbye 100次。 这工作正常,但是,在打印之后,程序挂起并且没有完成。 我有一种感觉,因为线程没有完成。
我想知道最好的办法是什么?
所以我的主要是这样的
public static void main(String [] args)
{
Object lock = new Object();
new HelloThread(lock).start();
new GoodbyeThread(lock).start();
}
这是HelloThread类。 GoodbyeThread看起来一样:
class HelloThread extends Thread
{
private Object lock;
private boolean isRunning = false;
HelloThread(Object l)
{
this.lock = l;
}
public void run()
{
for(int i = 0; i < 100; i++)
{
synchronized(lock)
{
isRunning = true;
System.out.println("Hello");
lock.notify();
try
{
lock.wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
我在想可能有一种方法可以使用isRunning变量来关闭线程,但是我不确定最好的方法是什么。 谢谢你的帮助
答案 0 :(得分:1)
这样工作正常,但是在打印之后,程序挂起并且没有完成。我有一种感觉,因为线程没有完成。
如果线程正在离开run()
方法,那么它将完成。我怀疑在lock.wait()
的第100次打印后,您的帖子卡在"Hello"
上。如果您使用jconsole或dump a thread stack trace,您应该能够看到线程卡在哪里。
要认识到的一件事是,如果您调用lock.notify()
,则另一个线程将获得通知的唯一时间是lock.wait()
。通知呼叫不排队。
答案 1 :(得分:1)
for循环并不重要,关键的事情发生在最后一次迭代中。在另一个线程已经执行其wait()
之后,其中一个线程很可能会进入其notify()
,从而错过了突破wait()
的唯一机会。
答案 2 :(得分:1)
你的GoodbyeThread正在等待你的HelloThread发送一个notify()。
i == 99可能会发生什么:
HelloThread打印“Hello”调用notify(),然后调用wait()
GoodbyeThread打印“Goodbye”调用notify()[此处HelloThread退出for循环并终止],然后调用wait()。
什么都不会调用notify()来结束GoodbyeThread的wait()。
一个修复方法是只调用wait()如果i&lt; 99。
答案 3 :(得分:0)
如上所述:该线程处于死锁状态,因为其中至少有一个仍在等待notify()调用。
想象一下你只有一次跑步(只打印一次“Hello world”):
lock
,但此线程仍由线程B保持,因此线程A必须等待更长时间。线程B仍在等待,但永远不会被唤醒。
这可以通过这样的退出通知来解决:
for(int i = 0; i < 100; i++) {
// ...
}
synchronized (lock) {
lock.notifyAll();
}
wait / notify构造是最基本的线程工具,并不适合许多线程问题,因为它们经常会导致死锁或更糟。对于更容易且不易出错的线程概念,您应该使用concurrent package,它有现成的工具可用于解决大多数问题。
但是必须熟悉这些工具,并且绝对必须围绕这些工具设计代码,反之亦然。现有程序不能只是填充多线程以使其更快,它需要在您编写第一行代码之前为其设计。否则会遇到很多问题,包括结果可能比单线程执行速度慢。