gpt4 book ai didi

java - 如何使用 CyclingBarrier 同步线程并保留其执行顺序?

转载 作者:行者123 更新时间:2023-12-01 19:34:43 24 4
gpt4 key购买 nike

我想编写一个多线程应用程序,它可以逐个打印字符串中的字符,并且在第一个“回合”之后,它将保留其他回合的顺序。它应该像这样工作:

对于字符串:

private String[] strings = {"aaaa", "bb", "ccccccccccccc", "dddddd"};

它会打印:

abcd abcd acd acd cd cd c c c c c c c

或者也许

dbac dbac dac dac dc dc c c c c c c c

取决于第一轮中首先启动的进程

到目前为止我的解决方案如下

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Printer {

private CyclicBarrier cyclicBarrier;

private final static String one = "aaa";
private final static String two = "bbbb";
private final static String three = "c";
private final static String four = "dddddd";

public static void main(String[] args) {
Printer printer = new Printer();
printer.runSimulation(4);
}

private void runSimulation(int numberOfStrings) {
cyclicBarrier = new CyclicBarrier(numberOfStrings, new AggregatorThread());

Thread thread = new Thread(new PrintingThread(padSpaces(one, 10)));
Thread thread1 = new Thread(new PrintingThread(padSpaces(two, 10)));
Thread thread3 = new Thread(new PrintingThread(padSpaces(three, 10)));
Thread thread4 = new Thread(new PrintingThread(padSpaces(four, 10)));
thread.start();
thread1.start();
thread3.start();
thread4.start();
}

class AggregatorThread implements Runnable{
@Override
public void run() {
System.out.print(" ");
}
}

class PrintingThread implements Runnable{

private String toPrint;
private int iterator;

public PrintingThread(String toPrint) {
this.toPrint = toPrint;
this.iterator = 0;
}

@Override
public void run() {
while(iterator < toPrint.length()) {
System.out.print(toPrint.charAt(iterator));
iterator++;
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}

private String padSpaces(String inputString, int length) {
if (inputString.length() >= length) {
return inputString;
}
StringBuilder sb = new StringBuilder();
while (sb.length() < length - inputString.length()) {
sb.append(' ');
}
StringBuilder sb1 = new StringBuilder(inputString);
sb1.append(sb);

return sb1.toString();
}
}

但它不会保留写入控制台的字母顺序,而且我现在将字符串填充为一些硬编码值,但我希望它在没有相同字符串的情况下正常工作。对此有何建议?

最佳答案

既然您正在寻求使用 CyclicBarrier 的解决方案,那么您可以使用以下一种方法来实现此目的...这绝对不是我的第一个想法如何解决该问题(假设问题不是“使用 CyclicBarrier 执行此操作”...)。

  • 创建长度为 4 的 CyclicBarrier
  • 在每个线程启动时为其分配一个数字(0到3)(使用AtomicInteger或其他方式)。
  • 让每个线程执行以下操作:

    while (barrier.getNumberWaiting() != this.threadNumber) {
    }

    // Do your adding to the StringBuilder here...

    barrier.await();

即每个Thread 都会旋转,直到等待方的数量等于该Thread 的数量。

无论哪一个被分配了 0,都将始终首先通过,而所有其他的都被卡住旋转。一旦该Thread 完成其StringBuilder 操作,它就会await,这又会释放分配了1 的Thread去经历。编号分配后顺序将保持一致。

<小时/>

要获取每个进程的唯一 ID,可以使用简单的 AtomicInteger

private final AtomicInteger idCounter = new AtomicInteger();
private final CyclicBarrier barrier = new CyclicBarrier(4);
private final AtomicInteger doneCounter = new AtomicInteger();

public Runnable createRunnable() {
return () -> {
final int threadId = this.idCounter.getAndIncrement();

boolean threadDone = false;
boolean moreCharacters = true;
while (true) {
while (this.barrier.getNumberWaiting() != threadId) {
}

// Add to StringBuilder here...

// Set the 'moreCharacters' flag as false once this thread
// has handled its String.
// They will still need to spin though, to make sure the
// parties waiting keep adding up as appropriate.

if (!moreCharacters && !threadDone) {

// 'threadDone' used so that each thread only
// increments the 'doneCounter' once.

this.doneCounter.incrementAndGet();
threadDone = true;
}

barrier.await();

if (this.doneCounter.get() == 4) {
// Exit out of the loop once all Threads are done.
break;
}
}
};
}

关于java - 如何使用 CyclingBarrier 同步线程并保留其执行顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59231461/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com