2011-10-02 105 views
1

我想创建一个系统,其中一个线程A将项目添加到一个缓冲区,然后另一个线程B负责读取它们输入的确切顺序的项目,然后做一些潜在的长期操作他们。同步FIFO缓冲区的使用

我最好的猜测:

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在线程期间调用没有任何并发​​访问异常的.add() B处理缓冲区的内容。

也许我正在反思这个?与人在一起安全吗?非常感谢您对这个问题的评价。

真诚,

周杰伦

回答

1

,你也可以对此感兴趣ArrayBlockingQueue类。

+0

确实有兴趣,但我的问题仍然存在:一个线程可以将队列add()添加到队列中,而另一个将队列remove()从队列中移除而没有任何并发​​访问问题? – Phaedrus

+0

使用BlockingQueue的答案是肯定的,它是线程安全的,因此您不必担心同步。 您可以阅读文档http://download.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html:“BlockingQueue实现是线程安全的。” –

+0

这是exacly我需要什么,谢谢。 - LinkedBlockingQueue Phaedrus

1

如果您有记录最快的办法可能是使用管道字符流。

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

打印

Took an average of 269 nano-seconds per line 

注:管材本身不会产生任何垃圾。 (不同于队列)


可以使用的ExecutorService如果我没有错的包队列和线程(S)

ExecutorService es = 

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

如果我正确理解你的话,这对我而言并不合适,因为队列中有数以百万计的项目,我只需要一个工作线程来处理它们。 – Phaedrus

+0

不知道为什么你想要数百万个物品排队。这听起来效率很低,但没有什么区别。您可以拥有数百万个任务和单个线程池。 –

+0

工作线程用于记录字符输出。主线程需要指示该角色需要被记录,然后继续进行更紧迫的工作。然后,工作线程需要从缓冲区中读取字符,并将它们写入文件,如果需要的话,需要时间。所以要回答你的问题,我的队列是一个字符队列。 – Phaedrus