Java 整数值未刷新
我试图使用两个单独的线程来打印偶数和奇数,它们通过wait和notify相互通信 我知道我指的是堆中的整数对象。因此,一个线程所做的更改应该对两个线程都可见。我还使用volatile关键字来声明integeti 我似乎无法理解变量I的值是如何显示为1的,即使它已递增。 代码的输出是Java 整数值未刷新,java,multithreading,Java,Multithreading,我试图使用两个单独的线程来打印偶数和奇数,它们通过wait和notify相互通信 我知道我指的是堆中的整数对象。因此,一个线程所做的更改应该对两个线程都可见。我还使用volatile关键字来声明integeti 我似乎无法理解变量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
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
打包程序;
公共课偶数{
静态对象lck=新对象();
可变静态整数i=1;
易失性静态整数N=1000;
公共静态void main(字符串参数[]){
EvenRunner e=新的EvenRunner(lck,i,N);
OddRunner o=新OddRunner(lck,i,N);
螺纹t1=新螺纹(e,“偶数螺纹”);
螺纹t2=新螺纹(o,“奇数螺纹”);
t1.start();
t2.start();
试一试{
t1.join();
t2.连接();
}捕获(中断异常例外){
System.out.println(“中断:+ex”);
}
}
}
类EvenRunner实现可运行{
对象lck;
整数i;
整数N;
EvenRunner(对象lck、整数i、整数N){
这个.lck=lck;
这个。i=i;
这个,N=N;
}
@凌驾
公开募捐{
而
预期的输出应该是,其他线程也应该在变量I递增后将其值视为2
在构造evenRunner
和oddRunner
时,将相同的Integer
引用作为实例字段复制到每个类中
但是Integer
是不可变的-当您执行++i;
时,它会更改字段以引用不同的Integer
对象。它不会修改现有Integer对象的内容…因此您的两个线程在完全不同的字段上操作,并且根本不会交互
如果您想要一个两个线程都可以修改的对象,请改用。作为旁白,我强烈建议您遵循Java命名约定,类名为EvenRunner
和OddRunner
。谢谢,先生,从下一次开始我会更加小心。因为整数是不可变的,所以无法修改它在其他线程中,引用它也会看到新值?对吗?如果我想要一个可变的共享对象而不是整数对象,我需要创建一个可变的共享对象。@ashish2199是的,这就是“不可变”的意思。另外,使用原语也没有帮助,因为它们是每个线程的本地对象,而其他线程不知道什么是i在其他线程中的值,因此两者之间没有同步。对吗?@ashish2199:这并不是说它是线程的本地值,而是每个对象都有一个单独的字段。即使只涉及一个线程,您也会在这里看到相同的行为。
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();
}
}
}
}