我是多线程的新手。我正在尝试编写一个程序,我有两个线程。一个线程打印奇数,然后使用wait()放弃监视器锁定,同样其他线程打印偶数并在打印数字后放弃锁定 我有4个班级
问题 - 我的代码大部分时间都按预期工作,即按顺序打印1到100。两个线程轮流。但是我注意到有一个bug。有时甚至线程会先安排好,然后输出低于输出
2 **********
1 ###############################
之后没有任何内容被打印出来,看起来有一个死锁的情况。我无法弄清楚原因。请帮我理解这个
public class SomeMaths {
public synchronized void printOdd(){
for( int i=1;i<=100;i++){
if(i%2 !=0) {
System.out.println(i + " ###############################");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify();
}
}
public synchronized void printEven(){
for(int i=1;i<=100;i++){
if(i%2 ==0){
System.out.println(i +" **********");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify();
}
}
}
public class Odd implements Runnable {
SomeMaths sm;
public Odd(SomeMaths sm){
this.sm = sm;
}
@Override
public void run(){
sm.printOdd();
}
}
public class Even extends Thread {
SomeMaths sm;
public Even(SomeMaths sm){
this.sm = sm;
}
@Override
public void run(){
sm.printEven();
}
}
public class OEApp {
public static void main(String[] args) {
SomeMaths sm = new SomeMaths();
Thread odd = new Thread(new Odd(sm));
Thread even = new Thread(new Even(sm));
odd.start();
even.start();
try {
odd.join();
even.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:6)
我相信它的运作方式如下:
即使是线程开始,1也是奇数,所以它调用notify(通知没有人),然后2就是如此,它会打印一条消息并等待
奇数线程开始,1是奇数,所以它打印一条消息并等待
没有人可以调用通知,因此两个线程都会永远等待
答案 1 :(得分:-2)
使用同步关键字的目的是什么?
它只能向您保证您的功能不会同时运行多次。
我假设你想要一个线程通知另一个线程?是吗?
但是,如果在等待之前调用通知会怎么样?
你知道你可以使用调试器来查看每个线程,从而知道每个线程被卡住的位置吗?
请记住,一旦调用 start ,就无法知道哪个线程有cpu时间。
此外,您正在尝试同步两个线程(通过使用通知/等待机制),但还有其他的机制可以证明更简单(例如信号量:每个线程都拥有它< strong>信号量,获取自己的信号量并释放另一个信号量;将每个信号量初始化为1并且它将顺利进行。
P.S。 :
我被迫发布答案,但应该是评论;遗憾
为什么同时使用runnable和thread接口?此外,你的Even类已经是一个线程了,所以没有必要再次包装它。
请参阅https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem