Jac*_*nds 39 java multithreading
我试图在多个线程中逐行读取套接字的输入.如何中断readLine()以便我可以优雅地阻止它阻塞的线程?
编辑(赏金):这可以在不关闭套接字的情况下完成吗?
Tom*_*ine 28
没有关闭套接字:
困难的问题不是BufferedReader.readLine,而是潜在的问题read.如果一个线程被阻塞读取,唯一的方法是提供一些实际数据或关闭套接字(中断线程可能应该工作,但实际上没有).
所以显而易见的解决方案是拥有两个线程.一个读取原始数据,并将保持阻止状态.第二个,将是线程调用readLine.从第一秒开始管道数据.然后,您可以访问锁定,而不是用于唤醒第二个线程,并让它采取适当的操作.
有变化.您可以使用NIO创建第一个线程,并在所有使用者之间共享一个线程实例.
或者你可以写一个readLine适用于NIO的.这甚至可以采用相对简单的单线程形式,因为它Selector.wakeup存在并且有效.
Ste*_*son 23
关闭中断线程上的套接字.这将导致在被中断的线程上抛出异常.
有关此问题和其他并发问题的更多信息,我强烈推荐Brian Goetz的书"Java Concurrency in Practice".
我最近玩这个(使用Scala),我不喜欢关闭套接字并获得异常的接受答案.
最终我发现可以 socket.shutdownInput()在中断线程中调用以无异常地退出readLine调用.我在一个SIGINT处理程序中进行此调用,以便我可以清理并关闭主线程中的套接字.
注意,输出流的等价物存在 socket.shutdownOutput()
很抱歉超过6年;-)从键盘读取时,我需要一些可中断的readLine,用于简单的爱好控制台应用程序.换句话说,我无法"关闭套接字".
正如你可能知道,System.in是的InputStream,显然已经做了一些缓冲(你需要按Enter]).但是,似乎建议将其包装在一起以BufferedReader获得更好的效率,因此我的输入来自:
BufferedReader consoleIn = new BufferedReader(new InputStreamReader(System.in));
人们可能发现的另一件事BufferedReader.readLine()是提供阻塞直到输入(即使线程被中断,这似乎只是一旦readline()获得其输入结束线程).不过,可以预测何时BufferedReader.read()将不会阻止,通过调用BufferedReader.ready() == true.(但是,== false不保证阻止,所以要小心.)
因此,我将上述想法合并到一个方法中,该方法BufferedReader逐字符地读取字符,如果线程被中断则在每个字符之间检查,并且还检查行尾,此时返回文本行.
您可能会发现此代码很有用,consoleIn如上所述传递变量.(批评也可能受到欢迎......):
private String interruptibleReadLine(BufferedReader reader)
throws InterruptedException, IOException {
Pattern line = Pattern.compile("^(.*)\\R");
Matcher matcher;
boolean interrupted = false;
StringBuilder result = new StringBuilder();
int chr = -1;
do {
if (reader.ready()) chr = reader.read();
if (chr > -1) result.append((char) chr);
matcher = line.matcher(result.toString());
interrupted = Thread.interrupted(); // resets flag, call only once
} while (!interrupted && !matcher.matches());
if (interrupted) throw new InterruptedException();
return (matcher.matches() ? matcher.group(1) : "");
}
Run Code Online (Sandbox Code Playgroud)
...在调用它的线程中,捕获异常并适当地结束线程.
这是在Linux上的Java 8中测试的.
| 归档时间: |
|
| 查看次数: |
28519 次 |
| 最近记录: |