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

小编典典

这是因为读取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()的调用中阻塞了(!)。另外,另一个测试程序(此处未显示)尝试关闭通道,但这也不起作用。

2020-09-21

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值