java - obj.notify()似乎不起作用

use*_*336 1 java multithreading synchronization deadlock notify

在我的java代码中,threadB创建了nb*threadA并等待,直到myobj的值等于nb. myobj最初等于0,每个threadA递增它,当它等于nb时,最后一个threadA通知ThreadB.

运行程序时,不会通知threadB并且不会继续运行.谁能告诉我这段代码中的问题在哪里?

public class Myclass {
    static Long myobj = new Long(0);
    static int nb = 1;

    public static void main(String[] args) {

        ThreadA[] threadA = new ThreadA[nb];
        ThreadB threadB = new ThreadB(threadA);
    }
}

public class ThreadA extends Thread {
    public ThreadA() {
        this.start();
    }

    public void run() {
        // do lot of computation
        Myclass.myobj = Myclass.myobj + 1;
        if (Myclass.myobj.intValue() == Myclass.myobj.nb) {
            synchronized (Myclass.myobj) {
                Myclass.myobj.notify();
            }
        }
    }
}

public class ThreadB extends Thread {
    ThreadA[] threadA;

    public ThreadB(ThreadA[] threadA) {
        this.threadA = threadA;
        this.start();
    }

    public void run() {
        for (int i = 0; i < threadA.length; i++) {
            threadA[i] = new ThreadA();
        }

        synchronized (Myclass.myobj) {
            while (Myclass.myobj.intValue() != Myclass.myobj.nb) {
                Myclass.myobj.wait();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*rey 9

我对所有可能出错但却没有引起问题的事情感到困惑.

真正的问题是

if (Myclass.myobj.intValue() == Myclass.myobj.nb)
Run Code Online (Sandbox Code Playgroud)

每次被称为myobj< 时,永远不会是真的nb


我该怎么写这段代码?

int nb = ....

ExecutorService es = Executors.newFixedThreadPool(nb)
for (int i = 0; i < nb; i++)
    es.submit(new Runnable() {
        @Override
        public void run() {
            // do lot of computation
        }
    });
es.shutdown();
es.awaitTermination(1, TimeUnit.HOURS);
Run Code Online (Sandbox Code Playgroud)

这里有很多东西需要改进,我觉得有必要列出它们

  • 使用正确的格式.
  • 提供可能编译的代码
  • 不要锁定可变字段.这不符合您的期望,因为您每次都会锁定不同的对象.
  • Long当你的意思是使用时不要使用long.在这个原因你似乎想要使用int.
  • 不要创建一个,new Long(0)因为你可以使用更高效的自动装箱.如果这样做,请不要将其用作锁定对象.
  • 不要static在线程之间使用可变字段.
  • 不要延长Thread.创建一个传递给线程的Runnable.
  • 不要在构造函数中启动一个线程.
  • 不要使用数组将线程传递给另一个线程.esp,直到该线程开始后才会设置.
  • 仅读取/检查同步块内的受保护值.
  • 我不会使用一个线程来创建另一个传递回原始线程的线程.

但是,您的基本问题是您正在等待与您通知的对象不同的对象.

synchronized(Myclass.myobj){ // lock the object you might be waiting on.
    Myclass.myobj=Myclass.myobj+1; // change this to another object.
    Myclass.myobj.notify(); // notify a different object.
}
Run Code Online (Sandbox Code Playgroud)