[英]Synchronize Three Threads
在面試中被問到這個問題,試圖解決...但是沒有成功。 我想到了使用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
誰能幫助我糾正錯誤?
是否需要使用單個 CyclicBarrier
? 我的建議是:
您應該創建一個循環圖
ThreadOne_1 -> ThreadOne_2 -> ThreadOne_3 -> ThreadOne_1 -> etc...
CyclicBarrier
,最后一個任務應該與第一個線程的子代共享其CB。 要回答您的問題:
試圖瀏覽文檔,但不清楚await()的確切功能...
等待將暫停自己,直到N
線程數已調用await
上的障礙。 因此,如果您定義了new CyclicBarrier(3)
,則一次調用3個線程await
,屏障將允許線程繼續。
何時使用reset()
您不需要,一旦線程數到達,它將自動觸發障礙
正如其他人已經提到的那樣,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();
}
}
這是一種使用同步,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();
}
}
}
由於螺紋應被賦予相等的重量,即第一,第二,第三。 以下作品。
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();
}
}
我已經使用事件編碼了一個三線程應用程序
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.