1

在我的 java 代码中, threadB 创建nb *threadA 并等待myobj的值等于nbmyobj最初等于 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();
            }
        }
    }
}
4

2 回答 2

9

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

真正的问题是

if (Myclass.myobj.intValue() == Myclass.myobj.nb)

永远不会是真的,因为每次这被称为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);

这里有很多需要改进的地方,我觉得有必要列出来

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

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

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.
}
于 2012-09-26T10:35:21.163 回答
2

您正在等待一个对象,并通知另一个对象,因为 ThreadA 将一个新对象分配给 Myclass.myobj 并通知这个新对象。

使用专用的锁定对象,并确保对 myObj 的每次访问都受到此锁定对象的保护。

或者更好的是,使用 java.util.concurrent 包中的更高级别的并发抽象。

于 2012-09-26T10:34:01.387 回答