我想开发一个包含两个线程thread1和thread2的应用程序。 线程1必须打印最多50个偶数,线程2必须打印奇数到50。 并且两个线程都应该通信,使得印刷者应该是1,250。 我尝试了以下代码。 如何在EvenThread和OddThread之间进行通信
public class TestPrint{
public static void main(String[] args) {
EvenThread et=new EvenThread();
OddThread ot=new OddThread();
et.start();
ot.start();
}
}
class EvenThread extends Thread{
int even=0;
@Override
public void run() {
synchronized(this){
while(even<50){
System.out.println(even);
even=even+2;
try {
this.wait();
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class OddThread extends Thread{
int odd=1;
@Override
public void run() {
synchronized(this){
while(odd<50){
System.out.println(odd);
odd=odd+2;
try {
this.wait();
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
答案 0 :(得分:0)
您的线程需要使用相同的锁。在您的代码中,您的两个线程中的每一个都有自己的锁,因为这两个线程是使用synchronized(this)
的单独对象。这意味着他们不等待轮流,当线程调用notify或notifyAll时它们不会得到通知(因为只有在同一个锁上等待的线程才收到通知)。
将锁对象添加到TestPrint类中,如下所示:
public static final Object LOCK = new Object();
让你的线程通过将其同步块更改为
来将其用作锁定synchronized(LOCK) {
另外,在调用wait之后调用notify的方式也没有意义。您需要在写完条目后使用notify,并在等待有机会写入时等待。你需要有一些标志(例如TestPrint类中的一个volatile变量),线程用它来决定它们何时可以行动,在确定何时采取行动时单独依赖通知是不安全的(因为线程可以从等待返回)没有得到通知)。
假设您向TestPrint添加了另一个字段,以保存要打印的下一个值:
public static int nextValue = 1;
然后OddThread可以有如下代码:
try {
synchronized(TestPrint.LOCK) {
// wait for nextValue to become odd
while (TestPrint.nextValue % 2 == 0) {
TestPrint.LOCK.wait();
}
// at this point oddthread has the lock,
// and nextValue is odd
System.out.println(TestPrint.nextValue);
TestPrint.nextValue += 1;
// tell the other thread it can proceed
TestPrint.LOCK.notify();
}
} catch (InterruptedException e) {
// won't happen (no one is calling interrupt
// on this thread)
}
有关使用wait和notify的示例,请参阅section of the Oracle tutorial that discusses guarded blocks。