Java 同步FIFO缓冲区使用

Java 同步FIFO缓冲区使用,java,buffer,synchronized,fifo,Java,Buffer,Synchronized,Fifo,我试图创建一个系统,其中一个线程a将项目添加到缓冲区,然后另一个线程B负责按照项目输入的确切顺序读取项目,然后对其执行一些潜在的长时间操作 我最好的猜测是: Class B extends Thread { Buffer fifo = BufferUtils.synchronizedBuffer(new BoundedFifoBuffer()); add(Object o) { // Thread A calls me, and doesn't deal well with

我试图创建一个系统,其中一个线程a将项目添加到缓冲区,然后另一个线程B负责按照项目输入的确切顺序读取项目,然后对其执行一些潜在的长时间操作

我最好的猜测是:

 Class B extends Thread {

    Buffer fifo = BufferUtils.synchronizedBuffer(new BoundedFifoBuffer());

    add(Object o) { // Thread A calls me, and doesn't deal well with delays :)
      fifo.add(o); // will the sync below prevent this from happening? 
                   // or can .add be independent of the sync ?
    }

    run() {
     synchronized (fifo) { // why am i sync'd here?  I am the only thread accessing...
         while ( item in buffer ) { // also how do i check this, and block otherwise?
            process(fifo.remove());
         }
     }
    |
  }
如您所见,我甚至不能完全确定是否需要同步。线程安全问题与get()访问无关,因为只有一个线程访问它,但最重要的是线程A在线程B处理缓冲区内容期间调用.add(),没有任何并发访问异常

也许我想得太多了?和你在一起安全吗?非常感谢你对这个问题的评价

真诚地


Jay

如果您有一个用于记录的字符流,最快的方法可能是使用管道

    PipedOutputStream pos = new PipedOutputStream();
    final PipedInputStream pis = new PipedInputStream(pos, 256*1024);
    ExecutorService es = Executors.newSingleThreadExecutor();
    es.execute(new Runnable() {
        @Override
        public void run() {
            byte[] bytes = new byte[256*1024];
            int length;
            try {
                while ((length = pis.read(bytes)) > 0) {
                    // something slow.
                    Thread.sleep(1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    // time latency
    PrintWriter pw = new PrintWriter(pos);
    long start = System.nanoTime();
    int runs = 10*1000*1000;
    for(int i=0;i<runs;i++) {
        pw.println("Hello "+i);
    }
    long time = System.nanoTime() - start;
    System.out.printf("Took an average of %,d nano-seconds per line%n", time/runs);
    es.shutdown();
注意:管道本身不会产生任何垃圾。(与队列不同)


您可以使用ExecutorService包装队列和线程


如果我没有错,您也可能对这个类感兴趣。

确实感兴趣,但我的问题是:一个线程是否可以将()添加到队列中,而另一个线程是否可以从队列中删除()而不存在任何并发访问问题?对于BlockingQueue,答案是肯定的,它是线程安全的,因此您不必担心同步问题。您可以阅读文档:“BlockingQueue实现是线程安全的…”这正是我需要的,谢谢。-LinkedBlockingQueueThank,我显然没有意识到这一点。如果我理解正确,这在我的情况下是不合适的,因为队列中有数百万个项目,而我只需要一个工作线程来处理它们。我不确定你为什么要让数百万个项目排队。这听起来效率很低,但没什么区别。您可以有数百万个任务和一个单线程池。工作线程用于记录字符输出。主线程需要指示需要记录角色,然后继续进行更为紧迫的工作。然后,工作线程需要从缓冲区读取字符并将其写入文件,如果需要,需要花费时间。为了回答你的问题,我的队列是一个字符队列。
    Took an average of 269 nano-seconds per line
ExecutorService es =

es.submit(new Runnable() {
  public void run() {
     process(o);
  }
});