Question
Specifically, the problem is to write a method like this:
- int maybeRead(InputStream in, long timeout)
How-To
Assuming your stream is not backed by a socket (so you can't use Socket.setSoTimeout()), I think the standard way of solving this type of problem is to use aFuture. Suppose I have the following executor and streams:
- ExecutorService executor = Executors.newFixedThreadPool(2);
- final PipedOutputStream outputStream = new PipedOutputStream();
- final PipedInputStream inputStream = new PipedInputStream(outputStream);
- Runnable writeTask = new Runnable() {
- @Override
- public void run() {
- try {
- outputStream.write(1);
- outputStream.write(2);
- Thread.sleep(5000);
- outputStream.write(3);
- outputStream.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- executor.submit(writeTask);
- long start = System.currentTimeMillis();
- int readByte = 1;
- // Read data without timeout
- while (readByte >= 0) {
- readByte = inputStream.read();
- if (readByte >= 0)
- System.out.println("Read: " + readByte);
- }
- System.out.println("Complete in " + (System.currentTimeMillis() - start) + "ms");
- executor.shutdown()
If there was a more fundamental problem, like the writer not responding, the reader would block for ever. If I wrap the read in a future, I can then control the timeout as follows:
- int readByte = 1;
- // Read data with timeout
- Callable
readTask = new Callable () { - @Override
- public Integer call() throws Exception
- {
- return inputStream.read();
- }
- };
- try
- {
- while (readByte >= 0)
- {
- Future
future = executor.submit(readTask); - readByte = future.get(1000, TimeUnit.MILLISECONDS);
- if (readByte >= 0) System.out.println("Read: " + readByte);
- }
- }
- catch(Exception e){System.err.printf("\t[Error] %s\n", e)}
Supplement
* Java concurrency (multi-threading) - Tutorial
沒有留言:
張貼留言