我试图解决多线程问题,但我很难了解其行为。
问题是: 有2个线程同时消耗偶数和奇数数字。我必须在它们之间引入线程通信以使自然顺序中的“消费”。
这是我的代码
public class EvenOddDemo {
public static void main(String[] args) {
Number n = new Number();
EvenThread et = new EvenThread(n);
OddThread ot = new OddThread(n);
et.start();
ot.start();
}
}
class EvenThread extends Thread {
private Number number;
public EvenThread(Number number) {
this.number = number;
}
@Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(number.getEven());
}
}
}
class OddThread extends Thread {
private Number number;
public OddThread(Number number) {
this.number = number;
}
@Override
public void run() {
for(int i=0; i<5; i++) {
System.out.println(number.getOdd());
}
}
}
class Number {
private int currentEven = 0;
private int currentOdd = 1;
private volatile String last = "odd";
public synchronized int getEven() {
if("even".equals(last)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = currentEven;
last = "even";
currentEven +=2;
notify();
return i;
}
public synchronized int getOdd() {
if("odd".equals(last)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = currentOdd;
last = "odd";
currentOdd +=2;
notify();
return i;
}
}
,输出
0
2
1
3
4
5
7
6
8
9
但是当我调试代码时,它会以正确的顺序打印数字。因此,我无法弄清楚我错过了什么。请帮我。提前感谢您抽出这个帖子的时间。
答案 0 :(得分:5)
据我所知,没有什么可以防止这种情况发生,解释了为什么2
在输出1
之前显示:
OddThread EvenThread
---------- ----------
gets odd
gets even
prints even
prints odd
锁定因此需要围绕整个序列“get / print”。
你会注意到你的输出中你永远不会“分开两个数字”。
答案 1 :(得分:2)
notify选择任何可用的帖子。
选择是任意的,由实施决定
如果有两个以上的线程在等待,则可能是“错误”线程的信号。
另外,请注意,两个线程都可以在get(偶数| Odd)中完成而不等待,导致通知无处可寻,具体取决于调度。
您需要更严格以确保订购。也许两把锁,偶数和奇数,都会有所帮助。
答案 2 :(得分:0)
您需要在getEven和getOdd函数中打印该数字并通知另一个线程。 但你在通知和打印号码,所以在noti之间 修改后的代码:
public class ThreadExp {
public static void main(String[] args) {
Number n = new Number();
EvenThread et = new EvenThread(n);
OddThread ot = new OddThread(n);
et.start();
ot.start();
}
}
class EvenThread extends Thread {
private Number number;
public EvenThread(Number number) {
this.number = number;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
number.getEven();
}
}
}
class OddThread extends Thread {
private Number number;
public OddThread(Number number) {
this.number = number;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
number.getOdd();
}
}
}
class Number {
private int currentEven = 0;
private int currentOdd = 1;
private StringBuilder odd;
private StringBuilder even;
private StringBuilder last;
{
odd = new StringBuilder("odd");
even = new StringBuilder("even");
last = odd;
}
public synchronized void getEven() {
if (last == even) {
try {
//System.out.println("inside if in even--->" +Thread.currentThread());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("out of if in even--> " + Thread.currentThread());
int i = currentEven;
last = even;
currentEven += 2;
System.out.println(i);
notify();
return;
}
public synchronized void getOdd() {
if (last == odd) {
try {
//System.out.println("inside if in odd--->" +Thread.currentThread());
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("out of if in odd--> " + Thread.currentThread());
int i = currentOdd;
last = odd;
currentOdd += 2;
System.out.println(i);
notify();
return;
}
}