java - 线程执行不可预测

标签 java multithreading

我正在启动两个线程 T1 打印 1,3,5,..... 和线程两个 T2 打印 2,4,6.... 下面是执行此操作的代码。

    public class T1T2Print {
    public static void main(String[] args) {
        Counter c = new Counter();
        c.count = 1;
        printThread t1 = new printThread(c);
        Thread T1 = new Thread(t1);
        T1.setName("T1");
        printThread t2 = new printThread(c);
        Thread T2 = new Thread(t2);
        T2.setName("T2");
        T2.start();
        T1.start();
    }

}

class printThread implements Runnable {
    public Counter count;
    public int reminder;



public printThread(Counter count) {
    this.count = count;
}

public void run() {
    for (int i = 1; i <= 5; i++) {
        synchronized (count) {
            String name = Thread.currentThread().getName();

            if (count.count % 2 != 0 && !name.equals("T1")) {
                try {
                    count.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println(name + " :: " + count.count);
                count.count++;
                count.notify();
            }

            if (count.count % 2 == 0 && !name.equals("T2")) {
                try {
                    count.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println(name + " :: " + count.count);
                count.count++;
                count.notify();
            }

        }
    }
}
}

输出如下:

T1 :: 1
T2 :: 2
T1 :: 3
T2 :: 4
T1 :: 5
T2 :: 6
T1 :: 7
T2 :: 8
T1 :: 9
T2 :: 10

但是当我将启动线程的顺序更改为

 T1.start();
 T2.start();

输出变化如下,为什么会这样

T1 :: 1
T2 :: 2
T2 :: 3
T2 :: 4
T2 :: 5
T2 :: 6
T2 :: 7
T2 :: 8
T2 :: 9
T2 :: 10
T2 :: 11
T1 :: 12
T1 :: 13
T1 :: 14
T1 :: 15
T1 :: 16
T1 :: 17
T1 :: 18
T1 :: 19

最佳答案

让我们在 count.wait() 调用之前添加 System.out.println(name + "::waits");

然后是第一个案例日志:

T2 :: waits
T1 :: 1
T1 :: waits
T2 :: 2
T2 :: waits
T1 :: 3
T1 :: waits
T2 :: 4
T2 :: waits
T1 :: 5
T1 :: waits
T2 :: 6
T2 :: waits
T1 :: 7
T1 :: waits
T2 :: 8
T2 :: waits
T1 :: 9
T1 :: waits
T2 :: 10

案例二:

T1 :: 1
T1 :: waits
T2 :: 2
T2 :: 3
T1 :: 4
T1 :: 5
T1 :: 6
T1 :: 7
T1 :: 8
T1 :: 9
T1 :: 10
T1 :: 11
T2 :: 12
T2 :: 13
T2 :: 14
T2 :: 15
T2 :: 16
T2 :: 17
T2 :: 18

正如您在第二种情况中看到的那样,线程不会 hibernate 。为什么?因为在第二种情况下,每个线程增加计数器两次(第一个 if 一次,第二个 if 一次)(并在同步中执行方式)。 (我可以假设你不想要这个逻辑,这是你犯的错误)。这两种情况有什么区别?在第一种情况下 T2 更早开始并在第一个中等待,如果在收到通知后它醒来并转到第二个如果,即它每次迭代仅增加(并打印)计数器一次.这就是为什么。

关于java - 线程执行不可预测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39848750/

相关文章:

java - 如何将 String 转换为 VariableBinding ? (org.snmp4j.mp.SnmpConstants)

Java线程垃圾回收

Python threading.thread.start() 不会将控制权返回给主线程

java - 为什么ExecutorService不调用UncaughtExceptionHandler?

java - Project Reactor 并行执行

java - Android 如何在 ListView 中设置列表<String>

java - 多线程服务器: SwingWorker Vs Thread?

c++ - 如何将 void (__thiscall MyClass::* )(void *) 转换为 void (__cdecl *)(void *) 指针

java - 从 Java 对象发布到 Clojure channel

java - 是否可以在 java 应用程序 Netbeans 中使用 Iframe 网页