有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Implement Runnable未显示正确的结果

我试图对一个类使用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();
    }
}

共 (3) 个答案

  1. # 1 楼答案

    synchronized(this)
    

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

  2. # 2 楼答案

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

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

    因为您试图对静态变量进行同步,所以必须使用synchronized static方法

    请参见此处的更多详细信息: 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();
        }
    }
    
  3. # 3 楼答案

    我已经调试了你的代码并找到了原因:

    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
    

    另外,示例中的第二个线程实际上没有进入wait()状态

    但是,由于通过第二个线程将a设置为0,第一个线程跳过了这个周期:

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

    这就是为什么你看不到第一个线程的输出。但它并没有停留在等待()状态