简体   繁体   English

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

[英]The threads are not printing in a sequence in my program

I have the program below to sequence the 3 threads. 我有下面的程序来排序3个线程。 For example first the first thread should print followed by second and then third thread. 例如,首先应该打印第一个线程,然后是第二个线程然后是第三个线程。 Bu the program below is not actually doing that and printing some random sequence. 下面的程序实际上并没有这样做并打印一些随机序列。 I have seen some programs on stackoverflow itself which execute and try to print in sequence. 我在stackoverflow本身看到了一些程序,它们执行并尝试按顺序打印。

But I am really trying hard to understand why the program below is not working and what is the thing I am not able to understand. 但我真的很努力地理解为什么下面的程序不起作用,我无法理解的是什么。

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);
    }
}

The expected result should be 预期的结果应该是

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

But the actual result is 但实际结果是

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

Your code has 2 problems. 您的代码有2个问题。

1.) You check if it's a thread's turn to print with the nextTurn != turnId in an if statement. 1.)检查是否nextTurn != turnIdif语句中使用nextTurn != turnId进行打印。 That means that if a thread reaches this if , it's not the thread's turn, it waits once, can then be woken up again, it might still not be that thread's turn, but it doesn't check again and just continues executing out of order. 这意味着,如果一个线程到达这个if ,它不是线程的转,等待一次,然后可以再次唤醒时,它仍然可能不是线程的转弯,但它不会再次检查,只是继续执行乱序。

To fix that, turn this if into a while . 要解决这个问题, if转换为一段while

2.) notify() does not wake up all waiting threads. 2.) notify()不会唤醒所有等待的线程。 That means that you might get a situation where the wrong thread is woken up, check's and sees that it's not the thread's turn yet, goes to sleep again, and then the notify() call is never reached, so the right thread is never woken up. 这意味着你可能会遇到一个错误的线程被唤醒的情况,检查并看到它还没有线程,再次进入休眠状态,然后永远不会达到notify()调用,所以正确的线程永远不会被唤醒起来。 In that case we are dealocked, unless a spurious wakeup occurs. 在这种情况下,除非发生虚假的唤醒,否则我们会被处理。

For that you can use notifyAll() instead. 为此,您可以使用notifyAll()

After fixing those 2 things I'm seeing the expected output: 在解决了我看到预期输出的两件事之后:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM