0

我在寻找一个简单的生产者 - 在Java中实现消费,不想推倒重来Java示例

我不能找不到一个同时使用新并发程序包和任一管道类的示例

有没有使用PipedInputStream和新的Java并发包的例子?

有没有更好的方法没有使用管道类来完成这样的任务?

+0

你到底想要达到什么目的?你提出了一个非常广泛的问题。如果我使用管道流,我不会介意刚开始一个线程。 –

+0

你只是想为消费者和生产者制作'Runnable'并将它们提交给'ExecutorService'? – trutheality

+0

只需从数据库中读取任务,并以非阻塞/异步/缓冲的方式写入文件,问题中提到的工具就是我认为是工作的正确工具,如果有更简单/不同的方式,我会很高兴听到 –

回答

4

对于您的任务,只需使用单个线程并使用BufferedOutputStream写入文件就足够了,正如您从数据库读取的那样。

如果你想在缓冲区大小和块的大小更多的控制被写入文件,你可以这样做:

class Producer implements Runnable { 

    private final OutputStream out; 
    private final SomeDBClass db; 

    public Producer(OutputStream out, SomeDBClass db){ 
     this.out = out; 
     this.db = db; 
    } 

    public void run(){ 
     // If you're writing to a text file you might want to wrap 
     // out in a Writer instead of using `write` directly. 
     while(db has more data){ 
      out.write(the data); 
     } 
     out.flush(); 
     out.close(); 
    } 
} 

class Consumer implements Runnable { 

    private final InputStream in; 
    private final OutputStream out; 
    public static final int CHUNKSIZE=512; 

    public Consumer(InputStream in, OutputStream out){ 
     this.out = out; 
     this.in = in; 
    } 

    public void run(){ 
     byte[] chunk = new byte[CHUNKSIZE]; 

     for(int bytesRead; -1 != (bytesRead = in.read(chunk,0,CHUNKSIZE));;){ 
      out.write(chunk, 0, bytesRead); 
     } 
     out.close(); 
    } 
} 

而在调用代码:

FileOutputStream toFile = // Open the stream to a file 
SomeDBClass db = // Set up the db connection 
PipedInputStream pi = new PipedInputStream(); // Optionally specify a size 
PipedOutputStream po = new PipedOutputStream(pi); 

ExecutorService exec = Executors.newFixedThreadPool(2); 
exec.submit(new Producer(po, db)); 
exec.submit(new Consumer(pi, toFile)); 
exec.shutdown(); 
  • 也捕捉可能抛出的任何异常。

请注意,如果只是这样做,那么使用ExecutorService没有任何优势。执行器很有用,当你有很多任务(太多的同时在线程中启动它们)。在这里你只有两个线程必须同时运行,所以直接调用Thread#start将会减少开销。