我正在尝试使用两个单独的线程打印偶数和奇数,这两个线程通过等待和通知相互通信。
我确实知道我指的是堆中的Integer对象。因此,一个线程所做的更改应该对两个线程都可见。我也使用volatile关键字声明Integet i。
即使变量i递增后,我似乎也无法理解变量i的值如何显示为1。
代码输出为
Even Thread got lock i=1
Even Thread waiting.. i=1
Odd Thread got lock i=1
Odd Thread : i=2
Odd Thread Run called NotifyAll
Odd Thread got lock i=2
Odd Thread waiting.. i=2
Even Thread woken up.. i=1
Even Thread waiting.. i=1
package programs;
public class EvenOdd {
static Object lck = new Object();
volatile static Integer i=1;
volatile static Integer N = 1000;
public static void main(String args[]){
EvenRunner e = new EvenRunner(lck, i, N);
OddRunner o = new OddRunner(lck, i, N);
Thread t1 = new Thread(e,"Even Thread ");
Thread t2 = new Thread(o,"Odd Thread ");
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch(InterruptedException ex) {
System.out.println("Interrupted : "+ex);
}
}
}
class EvenRunner implements Runnable{
Object lck;
Integer i;
Integer N;
EvenRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
@Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Even Thread got lock i="+i);
while(i%2==1){
try {
System.out.println(" Even Thread waiting.. i="+i);
lck.wait();
System.out.println(" Even Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Even Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
class OddRunner implements Runnable{
Object lck;
Integer i;
Integer N;
OddRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
@Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Odd Thread got lock i="+i);
while(i%2==0){
try {
System.out.println(" Odd Thread waiting.. i="+i);
lck.wait();
System.out.println(" Odd Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Odd Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
预期结果:应该是其他线程在将变量I递增后也应将其值视为2。
实际结果:变量i的值即使在递增后也被其他线程读取为1。
答案 0 :(得分:5)
预期的输出应该是其他线程在将变量I递增后也将变量I的值视为2。
构造evenRunner
和oddRunner
时,会将相同的Integer
引用作为实例字段复制到每个类中。
但是Integer
是不可变的-执行++i;
会将字段更改为引用不同 Integer
对象。它不会修改现有整数对象的内容...因此,您的两个线程在完全独立的字段上运行,并且根本不会交互。
如果您想拥有两个线程都可以修改的单个对象,请改用AtomicInteger
。