如何创建3个将逐个工作的线程

时间:2018-03-13 18:15:35

标签: java multithreading

没有旗帜可以吗?我只能使用notify / wait / synchronized。 我想打印:worker1 worker2 worker3 worker1 worker2 ...但我有wait()/ notify()方法的竞争条件。

class ThirdWorker implements Runnable {
        @Override
        public void run(){
            for (int i = 0; i < a; i++) {
                synchronized (mutex3) {
                    System.out.println(Thread.currentThread().getName() + " worker3 " + (i + 1));
                    try {
                        mutex3.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (mutex) {
                        mutex.notify();
                    }
                }
            }
        }
    }

    class SecondWorker implements Runnable{
        @Override
        public void run() {
            synchronized (mutex) {
                new Thread(new ThirdWorker()).start();
            }
                for (int i = 0; i < a; i++) {
                    synchronized (mutex2) {
                        System.out.println(Thread.currentThread().getName() + " worker2 " + (i + 1));
                        synchronized (mutex3){
                            mutex3.notify();
                        }
                        try {
                            mutex2.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

            }
        }
    }

    class FirstWorker implements Runnable{ 
        @Override
        public void run() {
            synchronized (mutex) {
                new Thread(new SecondWorker()).start();
                for (int i = 0; i < a; i++) {
                    System.out.println(Thread.currentThread().getName() + " worker 1 " + (i+1));
                    try {
                        mutex.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (mutex2){
                        mutex2.notify();
                    }
                }
            }
        }
    }
    new Thread(new FirstWorker()).start();  

我知道使用旗帜很容易做到,但我不能。

1 个答案:

答案 0 :(得分:0)

这里有一个如何做到的例子。

注意:
属性turnIsFor是受保护的资源 线程创建为兄弟姐妹 用作监视器的对象(lock)除了那之外不用于任何其他内容 while包含lock.wait(),其条件应该使线程能够运行 locknotify都必须位于synchronized区块内 另请注意,我故意以随机顺序启动线程,但仍然按照共享属性nextTurnIsFor给出的预期顺序一次一个。

public class ThreeThreads {

    Thread t1, t2, t3;
    Lock lock = new Lock();
    int turnIsFor = 1;
    public static void main(String ... args) {
        ThreeThreads threeThreads = new ThreeThreads();
        threeThreads.run();
    }

    public ThreeThreads() {


        Runnable printName1 = new Runnable() {

            int turn = 1;

            @Override
            public void run() {
                while(true){
                    try {
                        synchronized(lock) {
                            while(turnIsFor != turn){
                                lock.wait();;
                            }
                            System.out.println( Thread.currentThread().getName());  
                            turnIsFor = 2;
                            lock.notifyAll();
                        }
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable printName2 = new Runnable() {

            int turn = 2;

            @Override
            public void run() {
                while(true) {
                    try {
                        synchronized(lock) {
                            while(turnIsFor != turn){
                                lock.wait();;
                            }
                            System.out.println( Thread.currentThread().getName());  
                            turnIsFor = 3;
                            lock.notifyAll();
                        }
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable printName3 = new Runnable() {

            int turn = 3;

            @Override
            public void run() {
                while(true) {
                    try {
                        synchronized(lock) {
                            while(turnIsFor != turn){
                                lock.wait();;
                            }
                            System.out.println( Thread.currentThread().getName());  
                            turnIsFor = 1;
                            lock.notifyAll();
                        }
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        t1 = new Thread(printName1, "Thread 1");
        t2 = new Thread(printName2, "Thread 2");
        t3 = new Thread(printName3, "Thread 3");

    }

    public void run() {
        t3.start();
        t1.start();
        t2.start();
    }


    private static final class Lock{};

}