基元无法打印有序序列

时间:2016-02-27 09:26:32

标签: java multithreading concurrency

我假设三个线程:Pa,Pb和Pc,这样Pa只能写字母'A',Pb字母'B'和Pc字母'C'。这三个过程是从1到100的循环,唯一的出路是三个字母的交替:ABCABCABCABC ....

我试图遵循这个解决方案,但原语没有任何效果https://stackoverflow.com/a/33655989/5183367

有一个例子:

class PHilo implements Runnable {
    public static int turn;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (this) {
                if (turn == 0) {
                    System.out.print("A");
                    turn = 1;
                    notify();
                } else {
                    try {
                        wait();
                        System.out.println("Esperando para imprimir A");
                    } catch (InterruptedException ie) {

                    }
                }

                if (turn == 1) {
                    System.out.print("B");
                    turn = 2;
                    notify();

                } else {
                    try {
                        wait();
                        System.out.println("Esperando para imprimir B");
                    } catch (InterruptedException ie) {

                    }
                }

                if (turn == 2) {
                    System.out.print("C");
                    turn = 0;
                    notify();
                } else {
                    try {
                        wait();
                        System.out.println("Esperando para imprimir C");
                    } catch (InterruptedException ie) {

                    }
                }
                System.out.println();
            }
        }
    }
}

public class Environment {
    public static void main(String[] args) {

        PHilo h = new PHilo();

        Thread t1 = new Thread(h);
        Thread t2 = new Thread(h);
        Thread t3 = new Thread(h);

        t1.start();
        t2.start();
        t3.start();

    }
}

1 个答案:

答案 0 :(得分:0)

由于您是从一个没有接受回复的问题开始的,我在这里添加了我的,以便您可以看到这是否是您需要的。

这是基于您拥有的代码构建的,所以可能有更好的方法来实现它。

我已经添加了对代码的评论,以便您可以看到我做了什么以及为什么。

class PHilo implements Runnable {

    public static int turn;

    // First of all we need a shared lock so that every thread can use it
    // Using synchronized(this) won't synchronize at all because each thread will synchronize on itself
    private final static Object lock = new Object();

    // Then we need a way to let each thread know what it should print
    // Following your convention, if myTurn is 0 it'll print A and so on
    private final int myTurn;

    // That's why I added this constructor
    public PHilo(int myTurn) {
        this.myTurn = myTurn;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            // Now we're syncing on lock which is shared, this prevents 2 thread from printing together and only one is allowed each time
            synchronized (lock) {
                // We need to wait while it's not our turn, and we use the while to prevent spurious wakeups
                while (myTurn != turn) {
                    try {
                        // We wait on the shared lock
                        lock.wait();
                    } catch (InterruptedException ie) {
                    }
                }
                // If we're here it means that we can print since it's our turn, so let's decide what to print
                switch (myTurn) {
                    case 0: {
                        System.out.print("A");
                        turn = 1;
                        // There's no need to notify here
                        break;
                    }
                    case 1: {
                        System.out.print("B");
                        turn = 2;
                        break;
                    }
                    case 2: {
                        System.out.print("C");
                        turn = 0;                            
                        break;
                    }
                }
                // It's always a good idea to use notifyAll instead of notify, so that we can awake all the waiting threads
                // It's thread's responsibility to check if it may run after the notifyAll, so we just wake all of them and let them choose who can go on
                lock.notifyAll();
                System.out.println();
            }
        }
    }
}

class Environment {

    public static void main(String[] args) {

        // We use the parameter for PHilo to identify the different threads
        Thread t1 = new Thread(new PHilo(0));
        Thread t2 = new Thread(new PHilo(1));
        Thread t3 = new Thread(new PHilo(2));

        t1.start();
        t2.start();
        t3.start();

    }
}

这是我得到的输出,希望这就是你要求的:

A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C