-3

我正在尝试使用线程在 Java 中打印一条语句,其中每个线程都应该打印该语句的一部分。但是,以下代码并不总是以正确的顺序输出语句。

class NewThread implements Runnable {
    String msg;
    Thread t;
    NewThread(String str) {
        t = new Thread(this);
        msg = str;
    }
    public void run() {
        PrintMsg(msg);
    }
    synchronized void PrintMsg(String msg) {
        System.out.println(msg);
        try {
            wait();
        } catch (InterruptedException e) {
            System.out.println("Exception");
        }
        System.out.println(msg);
        notify();
    }
}
class ThreadDemo {
    public static void main(String args[]) {
        NewThread t1, t2, t3;
        t1 = new NewThread("Humphry Dumprey");
        t2 = new NewThread("went to the hill");
        t3 = new NewThread("to fetch a pail of water");
        t1.t.start();
        t2.t.start();
        t3.t.start();
        try {
            t1.t.join();
            t2.t.join();
            t3.t.join();
        } catch (InterruptedException e) {
            System.out.println("Main Thread Interrupted");
        }
    }
}

我怀疑线程间通信有问题。

4

1 回答 1

1

我认为您的问题出在这种方法中:

synchronized void PrintMsg(String msg) {
    System.out.println(msg);
    try {
        wait();
    } catch (InterruptedException e) {
        System.out.println("Exception");
    }
    System.out.println(msg);
    notify();
}

调用它的线程将调用wait()这导致它们无限期地等待某人调用notify()。但是没有其他电话,notify()所以他们都会停在那里。

此外,因为该方法是synchronized每个线程也在等待它自己的NewThread实例。我认为您的意思是让所有线程等待并通知同一个对象?

来自评论:

想要等待一个线程,直到它完成编写语句的一部分。应该是这样的: 线程 1 打印“Humphry Dumprey” 线程 2 打印“去山上” 线程 3 打印“去取一桶水”,这三个线程应该按顺序执行,这样语句才能按正确的顺序打印.

我从来不明白这类问题。线程的全部意义在于并行异步运行。如果您希望他们连续打印 3 个内容,则应使用 1 个线程。

如果您需要为某些任务执行此操作,那么您可以使用几种不同的方法来执行此操作。

  • 每个线程可以在同一个AtomicInteger. 如果整数为 1,线程 #1 将打印,线程 #2 在整数为 2 时打印,...。您可以将顺序作为value字段传递给NewThread构造函数。在打印它们的值后,它们会增加整数和 notifyAll()。

    static final AtomicInteger counter = new AtomicInteger(1);
    ...
    synchronized (counter) {
        // looping like this is always recommended
        while (counter.get() != value) {
           counter.wait();
        }
        System.out.println(...);
        counter.incrementAndGet();
        counter.notifyAll();
    }
    
  • 你可以使用 2CountdownLatch所以线程 #2 调用countDown1.await();和线程 #3 等待countDown2.await();. 然后在线程#1 打印它调用的消息countDown1.countDown()之后,在线程#2 打印它调用的消息之后countDown2.countDown()

于 2013-06-11T18:17:31.697 回答