我有20个并行运行的线程。每个人都调用函数,获取200条记录并写入文件。我想随机化所有记录。有没有什么方法可以用这样的方式写入文件:我从一个线程获得10条记录,然后从下一条线程获得10条,依此类推?
答案 0 :(得分:0)
我是否有办法以这样的方式写入文件,即从一个线程获得10条记录,然后从下一条线程获得10条,依此类推?
如果我理解正确,你的问题是如何协调多个线程的输出,以便每个线程按特定顺序打印输出。
在这种情况下,我会使用" Queue"协调线程的工作。像票务系统这样的东西。如果队列的头部对应于线程id / name,那么该线程可以打印其输出(当它完成时,它将从队列的头部删除它的名称。)
单独的协调员将决定允许线程打印其输出的顺序。
例如:
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.stream.IntStream;
/**
*
*/
public class SchedulerExample {
public static final int BATCH_LINES = 3;
public static void main(String[] args) throws InterruptedException {
SchedulerExample schedulerExample = new SchedulerExample();
schedulerExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5);
Queue<String> queue = new ConcurrentLinkedQueue<>();
List<String> allowedWorkersNames = new ArrayList<>();
allowedWorkersNames.add("worker1");
allowedWorkersNames.add("worker2");
allowedWorkersNames.add("worker3");
executorService.submit(new Coordinator(allowedWorkersNames, queue));
executorService.submit(new Worker("worker1", queue, BATCH_LINES));
executorService.submit(new Worker("worker2", queue, BATCH_LINES));
executorService.submit(new Worker("worker3", queue, BATCH_LINES));
Thread.sleep(10000);
System.out.println("ending application");
executorService.shutdownNow();
executorService.awaitTermination(5, TimeUnit.SECONDS);
}
}
/**
* this class decides the order in which workers are allowed to print their outputs
*/
class Coordinator implements Callable<Void> {
private List<String> allowedWorkersNames = new ArrayList<>();
private Queue<String> queue;
public Coordinator(List<String> allowedWorkersNames, Queue<String> queue) {
this.allowedWorkersNames = allowedWorkersNames;
this.queue = queue;
}
@Override
public Void call() throws Exception {
while (true) {
if (queue.size() == 0) {
queue.addAll(allowedWorkersNames);
}
Thread.sleep(1000);
}
}
}
class Worker implements Runnable {
private String name;
private int linesCounter;
private Queue<String> queue;
private int batchLines;
public Worker(String name, Queue<String> queue, int batchLines) {
this.name = name;
this.queue = queue;
this.batchLines = batchLines;
}
@Override
public void run() {
while (true) {
// do some useful work here.
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(name + "was interrupted");
}
// now this thread is ready to print its output.
String currentHeadOfQueue = queue.peek();
if (currentHeadOfQueue != null && currentHeadOfQueue.compareTo(name) == 0) {
IntStream.rangeClosed(1, batchLines).
forEach(i -> {
linesCounter++;
System.out.println(name + " - line:" + linesCounter);
}
);
queue.remove();
}
}
}
}