为消费者 - 生产者使用ExecutorService和PipedReader / PipedWriter(或PipedInputStream / PipedOutputStream)的Java示例

时间:2012-05-01 21:01:05

标签: java producer-consumer executorservice java.util.concurrent

我正在寻找一个简单的生产者 - 用Java实现的消费者实现,并且不想重新发明轮子

我找不到一个同时使用新的并发包和任何一个Piped类

的例子

是否有一个使用PipedInputStream和新Java并发包的示例?

如果没有将Piped类用于此类任务,是否有更好的方法?

1 个答案:

答案 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将减少开销。