繁体   English   中英

从多个线程以随机顺序写入文件

[英]Write to file in random order from multiple threads

我有20个线程并行运行。 每个调用函数,获取200条记录并写入文件。 我想随机化所有记录。 有什么方法可以使我从一个线程中获取10条记录,然后从下一个线程中获取10条记录,以此类推?

有什么方法可以使我从一个线程中获取10条记录,然后从下一个线程中获取10条记录,以此类推?

如果我正确理解,您的问题是如何协调多个线程的输出,以便每个线程按特定顺序打印其输出。

在这种情况下,我将使用“队列”来协调线程的工作。 类似于票务系统。 如果队列的头部与线程ID /名称相对应,则该线程可以打印其输出(完成后,它将从队列的头部删除其名称)。

一个单独的协调器将决定允许线程以什么顺序打印其输出。

例如:

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();
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM