使用等待和通知从不同线程打印值

问题描述 投票:-3回答:4

我有三个线程ThreadA,ThreadB和ThreadC分别在循环中打印值A,B和C。我希望输出像A,B,C一样,然后再像是A,B和C,直到在线程中执行循环。我想使用wait和notify编写此示例程序。下面的代码显示了所需的输出,但是有时我在输出中仅看到“ A”,无法弄清楚情况。

public class ThreadOrder {

    public static void main(String[] args) {
        Object lockAB = new Object();
        Object lockBC = new Object();
        Object lockCA = new Object();

        Thread threadA = new Thread(new ThreadOrder().new ThreadA(lockAB, lockCA));
        Thread threadB = new Thread(new ThreadOrder().new ThreadB(lockAB, lockBC));
        Thread threadC = new Thread(new ThreadOrder().new ThreadC(lockBC, lockCA));

        threadA.start();
        threadB.start();
        threadC.start();
    }

    class ThreadA implements Runnable {
        Object lockAB;
        Object lockCA;

        public ThreadA(Object lockAB, Object lockCA) {
            this.lockAB = lockAB;
            this.lockCA = lockCA;
        }

        @Override
        public void run() {
            for(int i=0; i<3; i++) {
                if(i!=0) {
                    try {
                        synchronized (lockCA) {
                            lockCA.wait();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                synchronized (lockAB) {
                    lockAB.notify();
                }
            }
        }

    }

    class ThreadB implements Runnable {
        Object lockAB;
        Object lockBC;

        public ThreadB(Object lockAB, Object lockBC) {
            this.lockAB = lockAB;
            this.lockBC = lockBC;
        }

        @Override
        public void run() {
            for(int i=0; i<3; i++) {
                try {
                    synchronized (lockAB) {
                        lockAB.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B");
                synchronized (lockBC) {
                    lockBC.notify();
                }
            }
        }

    }

    class ThreadC implements Runnable {
        Object lockBC;
        Object lockCA;

        public ThreadC(Object lockBC, Object lockCA) {
            this.lockBC = lockBC;
            this.lockCA = lockCA;
        }

        @Override
        public void run() {
            for(int i=0; i<3; i++) {
                try {
                    synchronized (lockBC) {
                        lockBC.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("C");
                synchronized (lockCA) {
                    lockCA.notify();
                }
            }
        }

    }
}
java multithreading wait notify
4个回答
1
投票

您打电话给wait,但尚未测试是否有等待的对象。您调用了notify,但是您尚未更改通知另一个线程所需的任何内容。您具有所有这些synchronized方法,但是没有共享状态要保护的同步。

代码中的任何内容都没有任何意义,并且似乎您从根本上不了解wait / notify机制的作用。 wait函数允许线程等待某些共享状态更改,notify函数允许一个线程告诉其他线程某些共享状态已更改。但是必须有一些共享状态,因为wait / notify机制(与锁或Sempahore不同)在内部是无状态的。

您可能应该具有一些受同步保护的共享状态。它应该编码下一个线程。如果您需要打印,但是共享状态表明该轮到您了,那么您需要进行一些操作wait。当您进行打印并轮到另外一个线程打印时,那么您就可以notify其他线程。


0
投票

考虑通过阻塞队列来创建相互连接的线程环。然后,您可以在环上传递令牌。每个线程都在等待接收令牌,打印其输出,将令牌传递到环中的下一个线程,然后返回等待状态。


0
投票
package com.test.algorithms;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class PrintInOrder {

    private static Integer[] a = { 1, 1, 1 };
    private static Integer[] b = { 2, 2, 2 };
    private static Integer[] c = { 3, 3, 3 };
    private static Integer[] d = { 4, 4, 4 };

    public static void main(String[] args) throws InterruptedException {

        QueueOrder q1 = null;
        QueueOrder q2 = null;
        QueueOrder q3 = null;
        QueueOrder q4 = null;

        q1 = new QueueOrder(a);
        q2 = new QueueOrder(b);
        q3 = new QueueOrder(c);
        q4 = new QueueOrder(d);

        q1.setChild(q2);

        q2.setChild(q3);

        q3.setChild(q4);

        q4.setChild(q1);

        Thread t1 = new Thread(q1);
        Thread t2 = new Thread(q2);
        Thread t3 = new Thread(q3);
        Thread t4 = new Thread(q4);


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

        QueueOrder q = q1;

        while (!q.queue.isEmpty()) {

            synchronized (q) {
                if (!q.isPrinted) {
                    q.notify();
                    q.wait();
                }
            }
            q = q.child;
        }

        t1.join();
        t2.join();
        t3.join();
        t4.join();

    }

}

class QueueOrder implements Runnable {

    Integer[] arr;
    QueueOrder child;
    Queue<Integer> queue = new LinkedList<>();
    boolean isPrinted = false;

    QueueOrder(Integer[] arr) {
        this.arr = arr;
        queue.addAll(Arrays.asList(arr));
    }

    public QueueOrder getChild() {
        return child;
    }

    public void setChild(QueueOrder child) {
        this.child = child;
    }

    public void run() {

        while (!this.queue.isEmpty()) {

            synchronized (this) {
                if (!this.isPrinted) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                } 
            }

            System.out.print("**" + this.queue.poll());
            this.isPrinted = false;
            synchronized (this) {
                this.notify();
            }

        }
    }
}

0
投票
package com.test.algorithms;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class PrintInOrder1 {

    private static Integer[] a = { 1, 1, 1 };
    private static Integer[] b = { 2, 2, 2 };
    private static Integer[] c = { 3, 3, 3 };
    private static Integer[] d = { 4, 4, 4 };

    public static void main(String[] args) throws InterruptedException {

        QueueOrder1 q1 = null;
        QueueOrder1 q2 = null;
        QueueOrder1 q3 = null;
        QueueOrder1 q4 = null;

        q1 = new QueueOrder1(a);
        q2 = new QueueOrder1(b);
        q3 = new QueueOrder1(c);
        q4 = new QueueOrder1(d);

        q1.setChild(q2);
        q1.isPrinted = true;

        q2.setChild(q3);

        q3.setChild(q4);

        q4.setChild(q1);

        Thread t1 = new Thread(q1);
        Thread t2 = new Thread(q2);
        Thread t3 = new Thread(q3);
        Thread t4 = new Thread(q4);


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



        t1.join();
        t2.join();
        t3.join();
        t4.join();

    }

}

class QueueOrder1 implements Runnable {

    Integer[] arr;
    QueueOrder1 child;
    Queue<Integer> queue = new LinkedList<>();
    boolean isPrinted = false;

    QueueOrder1(Integer[] arr) {
        this.arr = arr;
        queue.addAll(Arrays.asList(arr));
    }

    public QueueOrder1 getChild() {
        return child;
    }

    public void setChild(QueueOrder1 child) {
        this.child = child;
    }

    public void run() {

        while (!this.queue.isEmpty()) {

            synchronized (this) {
                if (!this.isPrinted) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                } 
            }

            System.out.print("**" + this.queue.poll());
            this.isPrinted = false;
            synchronized (this.child) {
                if(!this.child.isPrinted) {
                    this.child.notify();
                }
            }

        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.