【问题标题】:Two threads writing to the same file两个线程写入同一个文件
【发布时间】:2011-11-19 09:30:45
【问题描述】:

我有多个线程(现在假设是两个),每个线程都检索一个 HTML 页面并将其内容写入一个文件。需要注意的是,每个线程都想写入同一个输出文件。具有 run() 方法的类是静态内部类。我想采取的方法是让每个线程将它想要写入的内容放入队列中。然后,在线程完成(或所有线程都完成)后,遍历队列并将内容打印到文件中。我不确定如何实现这一点。同样,实现可运行接口的类是静态的。我并不精通并发,也不一定想做任何花哨的事情。对于简单的实现有什么建议吗?

【问题讨论】:

    标签: java multithreading concurrency


    【解决方案1】:

    您可以使用 java.util.concurrent 包中的 BlockingQueue。您的每个线程都会将其输出放入队列,第三个线程会将元素从队列中取出并将它们写入文件。 Blocking Queue 的 API 页面上有一个示例,您应该可以将其用于您的实现。您只需要提供produceconsume 的实现即可。

    【讨论】:

    • 该示例显示消费者和生产者类都是非静态的。如果两个类都是静态的,它会起作用吗?
    • 好吧,因为消费者和生产者是线程,所以它们不能是静态的。 Java 中的线程实现了 Runnable 接口,并且必须实例化才能执行。但是当然,您可以重构方法以将元素插入队列并将它们取出到静态方法中,具体取决于您拥有的程序设计。
    【解决方案2】:

    您可以使用单线程 ExecutorService。这可用于在生成数据时写入数据(而不必等待。

    static final ExecutorService logger = Executors.newSingleThreadExecutor();
    
    static void writeToFile(final FileOutputStream fos, final String text) {
        logger.execute(new Runnable() {
            public void run() {
                try {
                    fos.write(text.getBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    

    【讨论】:

      【解决方案3】:

      您也可以使用synchronized 块。

      【讨论】:

      • 同步块是否进入实现Runnable的类的run()方法?你能发帖或指出一个例子的方向吗?
      【解决方案4】:

      嗯,根据你的描述,我认为你的制作人应该是这样的:

      private static final int CAPACITY = 10; // whatever you like here.
      private static Object locker = new Object();
      private static Queue<String> queue = new ArrayBlockingQueue<String>(CAPACITY);
      
      private static class ThreadTask implements Runnable {
      
          @Override
          public void run() {
      
              // retrieve page            
              // add result to queue
          }       
      }
      

      当然,你可以在一个Executor中执行这些ThreadTask,以便更好的利用系统资源,如果你实现了生产者-消费者队列系统,你的消费者线程也可以和生产者同时运行。

      【讨论】:

      • 不太确定你是否意识到这已经是生产者-消费者队列系统的一半,你有生产者,你有队列,你现在只需要一个消费者线程。此外,您应该删除同步,因为 ArrayBlockingQueue(BlockingQueue 的实现)是为并发访问而设计的。此外,只要没有并发运行的消费者,您可能希望降低容量,否则您的程序将阻塞。
      • 我认为容量是您要写入的总页数。当计算完成时,队列大小将等于容量。为了线程安全,你是对的,我编辑了。
      • 啊,好吧。如果程序总是会获取相同数量的页面,那就有意义了。
      猜你喜欢
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 2020-08-03
      • 1970-01-01
      相关资源
      最近更新 更多