首页 > 多线程顺序打印ABCD

多线程顺序打印ABCD

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NumberPrint implements Runnable {
    private int state = 0;
    private Lock lock = new ReentrantLock();
    private final int N = 4;
    private String[] chars = { "A", "B", "C", "D" };

    private NumberPrint() {
    }

    @Override
    public void run() {
        for (int i = 0; i < N; i++) {
            createThread(i);
        }
    }

    private void createThread(int i) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (state != i) {
                    };
                    lock.lock();
                    for (int j = 0; j < N; j++) {
                        System.out.println(chars[i]);
                    }
                    state = (i + 1) % 4;
                    System.out.println(state);
                } finally {
                    lock.unlock();
                }
            }
        }, "thread" + i).start();
    }

    public static void main(String[] args) {
        new NumberPrint().run();
    }
}

顺序打印ABCD,为什么有时结果会不对呢?


目测你也许应该把state设为volatile:

private volatile int state = 0;

我跑你的程序, 有时jvm会陷入死循环.
据我的经验看, 你的

while (state != i) {};

非常危险, java有可能会把这个优化为:
while (3 != 4) {};

从而陷入死循环. 具体还需要看jdk debug版本里看一下.


java cocurrency in practise:

... For example, had we "forgotten" to declare the variable asleep as
volatile in Listing 3.4, the server JVM could hoist the test out of
the loop (turning it into an infinite loop), ...

volatile boolean asleep;
...
while (!asleep)
    countSomeSheep();

如果有兴趣, 可以试试jdk fastdebug版本, 去读一读jit编译后的代码, 这里有很好的例子:
https://weblogs.java.net/blog/2008/03/30/deep-dive-assembly-code-java


state定义成AtomicInteger


用join很容易实现:

public class NumberPrint {
    private String[] chars = {"A", "B", "C", "D"};
    private final int N = 4;

    public void run() {
        for (int i = 0; i < N; i++) {
            createThread(i);
        }
    }

    private void createThread(final int i) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(chars[i]);
            }
        }, "thread" + i);
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new NumberPrint().run();
    }
}
【热门文章】
【热门文章】