在接受采访时被问到这个问题,试图解决它......但没有成功。 我想过使用CyclicBarrier
有三个线程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
任何人都可以帮我正确的答案吗?
类似的问题 Thread Synchronization - Synchronizing three threads to print 012012012012..... not working
答案 0 :(得分:2)
是否要求使用单 CyclicBarrier
?我的建议是:
您应该创建一个循环图,以便
ThreadOne_1 -> ThreadOne_2 -> ThreadOne_3 -> ThreadOne_1 -> etc...
CyclicBarrier
,并且最后一个任务应该与第一个Thread的孩子分享它的CB。回答你的问题:
尝试浏览文档,但不太清楚await()究竟做了什么......
Await将暂停,直到N
个线程在屏障上调用await
。因此,如果您定义new CyclicBarrier(3)
而不是一次3个线程调用await
,则屏障将允许线程继续。
何时使用reset()
您不需要,一旦线程数量达到
,它将自动跳闸答案 1 :(得分:2)
正如其他人已经提到的,CyclicBarrier并不是完成任务的最佳工具。
我也同意这样的观点,即解决方案是链接线程,让一个线程始终为下一个线程设置。
这是一个使用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非常麻烦:
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();
}
}
答案 2 :(得分:0)
这是一种使用synchronized,wait和notifyAll对任意数量的线程起作用的方法
turn
变量控制哪个是必须执行的线程。这样的线程执行任务,增加turn
(以模数线程),通知所有线程并进入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();
}
}
}
答案 3 :(得分:0)
由于螺纹应该具有相同的重量,即在第三个之后的第二个之后。以下作品。
public class MultiThreadSynchronize {
static int index = 0;
static Object lock = new Object();
static class NumberPrinter extends Thread {
private final int remainder;
private final int noOfThreads;
private int value;
public NumberPrinter(String name, int remainder, int noOfThreads, int value) {
super(name);
this.remainder = remainder;
this.noOfThreads = noOfThreads;
this.value = value;
}
@Override
public void run() {
while (index < 20) {
synchronized (lock) {
while ((index % noOfThreads) != remainder) {. // base condition where all threads except one waits.
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index++;
System.out.println(getName() + " " + value);
value += 3;
lock.notifyAll();
}
}
}
}
public static void main(String[] args) {
NumberPrinter numberPrinter1 = new NumberPrinter("First Thread", 0, 3, 1);
NumberPrinter numberPrinter2 = new NumberPrinter("Second Thread", 1, 3, 2);
NumberPrinter numberPrinter3 = new NumberPrinter("Third Thread", 2, 3, 3);
numberPrinter1.start(); numberPrinter2.start(); numberPrinter3.start();
}
}
答案 4 :(得分:0)
我已经使用事件对一个三线程应用程序进行了编码
#include <iostream>
#include <Windows.h>
#include <atomic>
using namespace std;
HANDLE firstThreadEvent = CreateEvent(NULL, true, true, NULL);
HANDLE secondThreadEvent = CreateEvent(NULL, true, false, NULL);
HANDLE thirdThreadEvent = CreateEvent(NULL, true, false, NULL);
std::atomic<int> m_int = 1;
DWORD WINAPI firstThreadFun(LPVOID lparam)
{
while (1)
{
::WaitForSingleObject(firstThreadEvent,INFINITE);
cout << "By first thread " << m_int << std::endl;
m_int++;
ResetEvent(firstThreadEvent);
SetEvent(secondThreadEvent);
}
}
DWORD WINAPI secondThreadFun(LPVOID lparam)
{
while (1)
{
::WaitForSingleObject(secondThreadEvent, INFINITE);
cout << "By second thread "<< m_int << std::endl;
m_int++;
ResetEvent(secondThreadEvent);
SetEvent(thirdThreadEvent);
}
}
DWORD WINAPI thirdThreadFun(LPVOID lparam)
{
while (1)
{
::WaitForSingleObject(thirdThreadEvent, INFINITE);
cout << "By third thread " << m_int << std::endl;
m_int++;
ResetEvent(thirdThreadEvent);
SetEvent(firstThreadEvent);
}
}
int main()
{
HANDLE hnd[3];
hnd[0] = CreateThread(NULL, 0, &firstThreadFun, NULL, 0, NULL);
hnd[1] = CreateThread(NULL, 0, &secondThreadFun, NULL, 0, NULL);
hnd[2] = CreateThread(NULL, 0, &thirdThreadFun, NULL, 0, NULL);
WaitForMultipleObjects(3, hnd, true, INFINITE);
CloseHandle(hnd[0]);
CloseHandle(hnd[1]);
CloseHandle(hnd[2]);
return 0;
}