当前位置: 首页 > 知识库问答 >
问题:

同步三个线程

宋育
2023-03-14

在采访中被问到这个问题,试图解决它。。。但并不成功。我想用自行车旅行车

有三个线程T1打印1,4,7... T2打印2,5,8......和T3打印3,6,9......你如何将这三个同步到打印序列1,2,3,4,5,6,7,8,9......

我试着写作

public class CyclicBarrierTest {
    public static void main(String[] args) {
        CyclicBarrier cBarrier = new CyclicBarrier(3);
        new Thread(new ThreadOne(cBarrier,1,10,"One")).start();
        new Thread(new ThreadOne(cBarrier,2,10,"Two")).start();
        new Thread(new ThreadOne(cBarrier,3,10,"Three")).start();
    }
}

class ThreadOne implements Runnable {
    private CyclicBarrier cb;
    private String name;
    private int startCounter;
    private int numOfPrints;

    public ThreadOne(CyclicBarrier cb, int startCounter,int numOfPrints,String name) {
        this.cb = cb;
        this.startCounter=startCounter;
        this.numOfPrints=numOfPrints;
        this.name=name;
    }

    @Override
    public void run() {
        for(int counter=0;counter<numOfPrints;counter++)
        {
            try {
            // System.out.println(">>"+name+"<< "+cb.await());
            cb.await();
            System.out.println("["+name+"] "+startCounter);
            cb.await();
            //System.out.println("<<"+name+">> "+cb.await());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        startCounter+=3;
        }
    }

}

输出

[Three] 3
[One] 1
[Two] 2
[One] 4
[Two] 5
[Three] 6
[Two] 8
[One] 7
[Three] 9
[One] 10
[Two] 11
[Three] 12
[Two] 14
[One] 13
[Three] 15
[One] 16
[Two] 17
[Three] 18
[Two] 20
[One] 19
[Three] 21
[One] 22
[Two] 23
[Three] 24
[Two] 26
[One] 25
[Three] 27
[One] 28
[Two] 29
[Three] 30

有人能帮我纠正错误吗?

类似的Ques线程同步-将三个线程同步到打印012。。。。。不起作用

共有3个答案

包修贤
2023-03-14

下面是一种方法,可以使用synchronized、wait和notifyAll来处理任意数量的线程
Aturn变量控制必须执行的线程。这样的线程执行任务,增加圈数(以线程的模数计算),通知所有线程,并进入while循环,等待再次轮到它。

public class Test2 {

    final static int LOOPS = 10;
    final static int NUM_TREADS = 3;

    static class Sequenced extends Thread {

        static int turn = 0;
        static int count = 0;
        static Object lock = new Object();
        final int order;

        public Sequenced(int order) {
            this.order = order;
        }

        @Override
        public void run() {
            synchronized (lock) {
                try {
                    for (int n = 0; n < LOOPS; ++n) {
                        while (turn != order) {
                            lock.wait();
                        }
                        ++count;
                        System.out.println("T" + (order + 1) + " " + count);
                        turn = (turn + 1) % NUM_TREADS;
                        lock.notifyAll();
                    }
                } catch (InterruptedException ex) {
                    // Nothing to do but to let the thread die.
                }
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {
        Sequenced[] threads = new Sequenced[NUM_TREADS];
        for (int n = 0; n < NUM_TREADS; ++n) {
            threads[n] = new Sequenced(n);
            threads[n].start();
        }
        for (int n = 0; n < NUM_TREADS; ++n) {
            threads[n].join();
        }
    }

}
冀啸
2023-03-14

是否需要使用单个CyclicBarrier?我的建议是:

>

  • 对于每个ThreadOne实例,分配两个CyclicBarrier
  • 你应该创建一个循环图,这样

    ThreadOne_1-

    要回答您的问题:

    我试着浏览文件,但不太清楚等待()做什么...

    直到有N个线程在屏障上调用了wait,它才会自动挂起。因此,如果您定义了新的CyclicBarrier(3),那么一旦有3个线程调用了wait,屏障就会允许线程继续运行。

    何时使用重置()

    你不需要,一旦线程数增加,它就会自动跳过障碍

  • 谷德本
    2023-03-14

    正如其他人已经提到的,CyclicBarrier并不是完成这项任务的最佳工具。

    我也同意这样的观点,即解决方案是链接线程,让一个线程为下一个线程设置运行。

    下面是一个使用信号量的实现:

    import java.util.concurrent.BrokenBarrierException; 
    import java.util.concurrent.Semaphore;
    
    public class PrintNumbersWithSemaphore implements Runnable {
    
    private final Semaphore previous;
    
    private final Semaphore next;
    
    private final int[] numbers;
    
    public PrintNumbersWithSemaphore(Semaphore previous, Semaphore next, int[] numbers) {
        this.previous = previous;
        this.next = next;
        this.numbers = numbers;
    }
    
    @Override
    public void run() {
    
        for (int i = 0; i < numbers.length; i++) {
            wait4Green();
    
            System.out.println(numbers[i]);
    
            switchGreen4Next();
        }
    }
    
    private void switchGreen4Next() {
            next.release();
    }
    
    private void wait4Green() {
        try {
            previous.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    static public void main(String argv[]) throws InterruptedException, BrokenBarrierException {
        Semaphore sem1 = new Semaphore(1);
        Semaphore sem2 = new Semaphore(1);
        Semaphore sem3 = new Semaphore(1);
        sem1.acquire();
        sem2.acquire();
        sem3.acquire();
        Thread t1 = new Thread(new PrintNumbersWithSemaphore(sem3, sem1, new int[] { 1, 4, 7 }));
        Thread t2 = new Thread(new PrintNumbersWithSemaphore(sem1, sem2, new int[] { 2, 5, 8 }));
        Thread t3 = new Thread(new PrintNumbersWithSemaphore(sem2, sem3, new int[] { 3, 6, 9 }));
        t1.start();
        t2.start();
        t3.start();
        sem3.release();
    
        t1.join();
        t2.join();
        t3.join();
    }
    
    }
    

    下面是另一个,在我看来,使用CyclicBarrier实现起来相当麻烦:

    import java.util.concurrent.BrokenBarrierException; 
    import java.util.concurrent.CyclicBarrier;
    
    public class PrintNumbersWithCyclicBarrier implements Runnable {
    
    private final CyclicBarrier previous;
    
    private final CyclicBarrier next;
    
    private final int[] numbers;
    
    public PrintNumbersWithCyclicBarrier(CyclicBarrier previous, CyclicBarrier next, int[] numbers) {
        this.previous = previous;
        this.next = next;
        this.numbers = numbers;
    }
    
    @Override
    public void run() {
    
        for (int i = 0; i < numbers.length; i++) {
            wait4Green();
    
            System.out.println(numbers[i]);
    
            switchRed4Myself();
    
            switchGreen4Next();
        }
    }
    
    private void switchGreen4Next() {
        try {
            next.await();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    private void switchRed4Myself() {
        previous.reset();
    }
    
    private void wait4Green() {
        try {
            previous.await();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    static public void main(String argv[]) throws InterruptedException, BrokenBarrierException {
        CyclicBarrier cb1 = new CyclicBarrier(2);
        CyclicBarrier cb2 = new CyclicBarrier(2);
        CyclicBarrier cb3 = new CyclicBarrier(2);
        Thread t1 = new Thread(new PrintNumbersWithCyclicBarrier(cb3, cb1, new int[] { 1, 4, 7 }));
        Thread t2 = new Thread(new PrintNumbersWithCyclicBarrier(cb1, cb2, new int[] { 2, 5, 8 }));
        Thread t3 = new Thread(new PrintNumbersWithCyclicBarrier(cb2, cb3, new int[] { 3, 6, 9 }));
        t1.start();
        t2.start();
        t3.start();
        cb3.await();
    
        t1.join();
        t2.join();
        t3.join();
    }
    
    }
    
     类似资料:
    • 问题内容: 在面试中被问到这个问题,试图解决…但是没有成功。我想到了使用CyclicBarrier 有三个线程T1打印1,4,7 … T2打印2,5,8 …,T3打印3,6,9…。您如何同步这三个来打印序列1,2,3,4,5,6,7,8,9…。 我尝试编写并运行以下代码 输出 谁能帮助我纠正错误? 类似的 线程同步查询-同步三个线程以打印012012012012.....无法正常工作 问题答案:

    • 问题内容: 我正在尝试同步三个线程以打印012012012012…。但是它不能正常工作。每个线程都分配有一个编号,当它从主线程接收到信号时将打印该编号。以下程序有问题,我无法捕获。 问题答案: 您需要更多的协调。该notify调用不会立即唤醒线程并强制其继续执行。相反,您可以考虑notify将电子邮件发送给线程以使其可以继续进行。想象一下,如果您想让3个朋友按顺序给您打电话。您向朋友1发送了一封电

    • 下面的代码创建了一个新的custom um < code > Thread ,并等待线程结束,直到主线程再次激活。 > < li >我不太明白它是如何工作的。为什么< code > myth read . wait();立即接到电话? < li> 为什么不改用< code>Thread.join()? 公共静态void main(String[] args) {

    • 所以我有一个代码: 所以我将线程添加到我的线程列表中,然后启动这些线程。这是MyThread类: 我想做一个程序来创建线程,将它们添加到列表中,调用它们,但是每个线程都应该等到前一个线程结束它的任务。因此输出应该如下所示: 如何使用实现这一点?我尝试了使用的不同方法,但失败了。

    • 互斥锁 条件变量 POSIX信号量