【问题标题】:Write to file in random order from multiple threads从多个线程以随机顺序写入文件
【发布时间】:2017-06-28 19:53:32
【问题描述】:

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

【问题讨论】:

  • 你能告诉我们你的代码吗?
  • 为什么它需要多线程而不是单线程在写入之前随机化列表?
  • @MatejKormuth 我正在考虑使用现有代码的方法......它属于 NDA
  • @twm 这是需要的,因为有数百万条记录,如果连续执行会花费很多时间。
  • @MadhavPatekar,如何发布一个裸露的、可运行的存根来反映问题所需的内容,但为了避免 NDA 而从头开始编写?

标签: java multithreading bufferedwriter


【解决方案1】:

有什么方法可以写入文件,从一个线程获取 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();
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多