Implement Runnable 没有显示正确的结果

Implement Runnable is not showing correct result

我正在尝试在 class 上使用 wait() 和 notify() 来通知等待线程,但情况是先进入同步块的人将等待其他人打印一些值并通知等待线程。但是等待线程一直在等待。哪里做错了。

public class MyRunnableClass implements Runnable {
public static boolean transfer = false;
public static boolean isAnyThreadWaiting = false;

int a=10;
@Override
public void run() {
    // TODO Auto-generated method stub

    synchronized(this) {    
        System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I first occuipied block");
        
        try {
            if(isAnyThreadWaiting)
                MyRunnableClass.transfer=true;

            if(!MyRunnableClass.transfer&&!isAnyThreadWaiting) {
                System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I am going to wait");
                while(!MyRunnableClass.transfer) {
                    isAnyThreadWaiting=true;
                    this.wait();
                }
                
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        for(int i=0; i<a;i++) {
            System.out.println("I am Thread : "+Thread.currentThread().getName()+" Value of  a is : "+i );
            
        }
        a=0;
        isAnyThreadWaiting=false;
        
        this.notify();
    
        
    }
    
}

public static void main(String [] args) throws InterruptedException {
MyRunnableClass runnable1= new MyRunnableClass();
Thread thread1=new Thread(runnable1,"t1");
Thread thread2=new Thread(runnable1,"t2");
    thread1. start();
    
    
    
    thread2. start();
    }
}
synchronized(this)

this 在你的两个线程中是相同的,因为你使用了相同的 Runnable 实例。 synchronized 确保两个线程不能同时在块内。这意味着一个线程位于 synchronized 块的开头,而另一个位于 wait。您需要将同步范围缩小到您实际使用共享状态的地方,即仅synchronized(this)实际引用的代码(读取写)两个线程都需要的变量。

在一个线程中对静态变量所做的更改对另一个线程不可见。因此,对于两个线程,总是 transfer == falseisAnyThreadWaiting == false.

这意味着两个线程都进入“wait()”块并永远卡在那里。

因为您正在尝试对静态变量进行同步,所以您将不得不使用同步静态方法。

在此处查看更多详细信息: How to synchronize a static variable among threads running different instances of a class in Java?

但更简单的解决方案是根本不使用静态变量。 在您的情况下,您对两个线程使用相同的对象,因此无论如何都不需要将变量设为静态:

private boolean transfer = false;
private boolean isAnyThreadWaiting = false;

完整的解决方案应如下所示:

public class MyRunnableClass implements Runnable {
private boolean transfer = false;
private boolean isAnyThreadWaiting = false;

int a=10;

@Override
public void run() {
    // TODO Auto-generated method stub

    synchronized(this) {    
        System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I first occuipied block");
        
        try {
            if(isAnyThreadWaiting)
                transfer=true;

            if(!transfer && !isAnyThreadWaiting) {
                System.out.println("I am Thread : "+Thread.currentThread().getName()+" and I am going to wait");
                while(!transfer) {
                    isAnyThreadWaiting=true;
                    this.wait();
                }
                
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        for(int i=0; i<a;i++) {
            System.out.println("I am Thread : "+Thread.currentThread().getName()+" Value of  a is : "+i );
            
        }
        a=0;
        isAnyThreadWaiting=false;
        
        this.notify();
    
        
    }
    
}

public static void main(String [] args) throws InterruptedException {
MyRunnableClass runnable1= new MyRunnableClass();
Thread thread1=new Thread(runnable1,"t1");
Thread thread2=new Thread(runnable1,"t2");
    thread1. start();
    
    
    
    thread2. start();
    }
}

我调试了你的代码,找到了原因:

a=0;

请删除这段代码,您将看到两个线程的输出:

I am Thread : t1 and I first occuipied block
I am Thread : t1 and I am going to wait
I am Thread : t2 and I first occuipied block
I am Thread : t2 Value of  a is : 0
I am Thread : t2 Value of  a is : 1
I am Thread : t2 Value of  a is : 2
I am Thread : t2 Value of  a is : 3
I am Thread : t2 Value of  a is : 4
I am Thread : t2 Value of  a is : 5
I am Thread : t2 Value of  a is : 6
I am Thread : t2 Value of  a is : 7
I am Thread : t2 Value of  a is : 8
I am Thread : t2 Value of  a is : 9
I am Thread : t1 Value of  a is : 0
I am Thread : t1 Value of  a is : 1
I am Thread : t1 Value of  a is : 2
I am Thread : t1 Value of  a is : 3
I am Thread : t1 Value of  a is : 4
I am Thread : t1 Value of  a is : 5
I am Thread : t1 Value of  a is : 6
I am Thread : t1 Value of  a is : 7
I am Thread : t1 Value of  a is : 8
I am Thread : t1 Value of  a is : 9

P.S。您示例中的第二个线程实际上没有进入 wait() 状态。

但是因为第二个线程把a设置为0,所以第一个线程跳过了这个循环:

for(int i=0; i<a;i++) {
    System.out.println("I am Thread : "+Thread.currentThread().getName()+" Value of  a is : "+i );
    
}

这就是为什么您看不到第一个线程的输出的原因。但它并没有卡在 wait() 状态。