如何在Java中的阻塞读取操作中停止线程等待?

我有一个执行以下代码的线程:

public void run() {

try {

int n = 0;

byte[] buffer = new byte[4096];

while ((n = in.read(buffer)) != -1) {

out.write(buffer, 0, n);

out.flush();

}

} catch (IOException e) {

System.out.println(e);

}

}

哪里inSystem.in。如何才能优雅地停止此类线程?关闭System.in或使用均Thread.interrupt无效。

回答:

这是因为读取System.in(InputStream)是一项阻塞操作。

在这里看是否可以从InputStream读取超时?

这是一种从System.in获取NIO FileChannel并使用超时检查数据可用性的方法,这是问题中所述问题的特例。在控制台上运行它,不要键入任何输入,然后等待结果。它已在Windows和Linux上的Java 6下成功测试。

import java.io.FileInputStream;

import java.io.FilterInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.lang.reflect.Field;

import java.nio.ByteBuffer;

import java.nio.channels.ClosedByInterruptException;

public class Main {

static final ByteBuffer buf = ByteBuffer.allocate(4096);

public static void main(String[] args) {

long timeout = 1000 * 5;

try {

InputStream in = extract(System.in);

if (! (in instanceof FileInputStream))

throw new RuntimeException(

"Could not extract a FileInputStream from STDIN.");

try {

int ret = maybeAvailable((FileInputStream)in, timeout);

System.out.println(

Integer.toString(ret) + " bytes were read.");

} finally {

in.close();

}

} catch (Exception e) {

throw new RuntimeException(e);

}

}

/* unravels all layers of FilterInputStream wrappers to get to the

* core InputStream

*/

public static InputStream extract(InputStream in)

throws NoSuchFieldException, IllegalAccessException {

Field f = FilterInputStream.class.getDeclaredField("in");

f.setAccessible(true);

while( in instanceof FilterInputStream )

in = (InputStream)f.get((FilterInputStream)in);

return in;

}

/* Returns the number of bytes which could be read from the stream,

* timing out after the specified number of milliseconds.

* Returns 0 on timeout (because no bytes could be read)

* and -1 for end of stream.

*/

public static int maybeAvailable(final FileInputStream in, long timeout)

throws IOException, InterruptedException {

final int[] dataReady = {0};

final IOException[] maybeException = {null};

final Thread reader = new Thread() {

public void run() {

try {

dataReady[0] = in.getChannel().read(buf);

} catch (ClosedByInterruptException e) {

System.err.println("Reader interrupted.");

} catch (IOException e) {

maybeException[0] = e;

}

}

};

Thread interruptor = new Thread() {

public void run() {

reader.interrupt();

}

};

reader.start();

for(;;) {

reader.join(timeout);

if (!reader.isAlive())

break;

interruptor.start();

interruptor.join(1000);

reader.join(1000);

if (!reader.isAlive())

break;

System.err.println("We're hung");

System.exit(1);

}

if ( maybeException[0] != null )

throw maybeException[0];

return dataReady[0];

}

}

有趣的是,在NetBeans 6.5中而不是在控制台中运行程序时,超时根本不起作用,并且实际上必须调用System.exit()来杀死僵尸线程。发生的情况是中断线程在对reader.interrupt()的调用中阻塞了(!)。另外,另一个测试程序(此处未显示)尝试关闭通道,但这也不起作用。

以上是 如何在Java中的阻塞读取操作中停止线程等待? 的全部内容, 来源链接: utcz.com/qa/402923.html

回到顶部