同步三个线程 [英] Synchronize Three Threads

查看:84
本文介绍了同步三个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在接受采访时被问到这个问题,试图解决它......但没有成功。
我想到使用CyclicBarrier

Was asked this question in an interview , tried to solve it ... but not successful. I thought of using CyclicBarrier

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

There are three threads T1 prints 1,4,7... T2 prints 2,5,8... and T3 prints 3,6,9 …. How do you synchronize these three to print sequence 1,2,3,4,5,6,7,8,9....

我试过写&运行以下代码

I tried writing & running the following code

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

任何人都可以帮我正确的答案吗?

Can anyone help me with correct ans ?

类似于问题
线程同步 - 同步三个线程打印012012012012 .....不工作

推荐答案

其他已经提到,CyclicBarrier并不是最好的工具任务。

As the others already mentioned, CyclicBarrier is not exactly the best tool for the task.

我也认为解决方案是将线程链接起来,让一个线程始终为下一个线程设置。

I also share the opinion that the solution is to chain the threads and let always one thread set the go for the next one.

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

Here goes an implementation using Semaphore:

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:

Here goes another one, in my opinion quite cumbersome implementation using 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();
}

}

这篇关于同步三个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆