线程不在我的程序中按顺序打印

时间:2019-06-07 21:18:19

标签: java multithreading

我有下面的程序对3个线程进行排序。 例如,应该先打印第一个线程,然后再打印第二个和第三个线程。 但是下面的程序实际上并没有这样做,而是打印了一些随机序列。 我已经在stackoverflow上看到了一些程序,这些程序会执行并尝试按顺序打印。

但是我真的很努力地理解为什么下面的程序无法正常工作以及我无法理解的是什么。

package my.tutorial.java;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class SequenceThreads {
    private static final Object lock = new Object();

    static class Task implements Runnable {
        private final String tName;
        private final int turnId;
        private static int nextTurn = 1;

        public Task(String tName, int turnId) {
            this.tName = tName;
            this.turnId = turnId;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (lock) {
                    if (nextTurn != turnId) {
                        try {
                            // System.out.println(tName + " went waiting   " + nCount);
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }

                    // System.out.println(tName + " went waiting");
                    System.out.println(tName + " Executed  ");
                    ++nextTurn;
                    if (nextTurn == 4)
                        nextTurn = 1;

                   // System.out.println(nextTurn);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock.notify();
                }


            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final Executor executor = Executors.newFixedThreadPool(3);
        //AtomicInteger nCount = new AtomicInteger(1);
        final Task task1 = new Task("T1", 1);
        final Task task2 = new Task("T2", 2);
        final Task task3 = new Task("T3", 3);
        executor.execute(task1);
        executor.execute(task2);
        executor.execute(task3);
    }
}

预期结果应该是

T1 Executed
T2 Executed
T3 Executed
T1 Executed
T2 Executed
T3 Executed

但是实际结果是

T1 Executed  
T2 Executed  
T1 Executed  
T1 Executed  
T3 Executed  
T3 Executed  
T1 Executed  
T3 Executed  
T3 Executed

1 个答案:

答案 0 :(得分:3)

您的代码有2个问题。

1。)您检查是否轮到在nextTurn != turnId语句中使用if打印。这意味着如果某个线程到达此if,则不是该线程了,它等待一次,然后又可以被唤醒,可能仍然不是该线程了,但是不再检查,只是继续无序执行。

要解决此问题,请将此if变成while

2。)notify()不会唤醒所有等待的线程。这意味着您可能会遇到以下情况:错误的线程被唤醒,检查并发现该线程不是轮到该线程了,再次进入睡眠状态,然后再也没有到达notify()调用,因此正确的线程是从来没有醒过。在这种情况下,除非发生虚假唤醒,否则我们会感到震惊。

为此,您可以改用notifyAll()

修复了这两件事之后,我看到了预期的输出:

T1 Executed  
T2 Executed  
T3 Executed  
T1 Executed  
T2 Executed  
T3 Executed  
T1 Executed  
T2 Executed  
T3 Executed
...