我试图通过Java中的TimerTask功能从main()启动一个周期任务,但run()任务挂起了。定时器之后的代码是一个REPL。代码如下所示:
public static void main( String[] asArguments ){
java.util.Timer timer = new Timer();
long durationDelay_ms = 60*60*1000; // 1 hour
long durationPeriod_ms = 60*60*1000; // 1 hour
timer.scheduleAtFixedRate( // reload prices every hour
new TimerTask() {
@Override
public void run() {
StringBuffer sbError = new StringBuffer();
if( ! reload( false, sbError ) ){
System.out.println( "error reloading prices: " );
}
sbError = null; // garbage collect
}
}, durationDelay_ms, durationPeriod_ms );
// REPL
BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
while( true ){
System.out.print( "> " );
try {
String s = br.readLine();
\\ ... code to process command
} catch( Throwable t ) {
\\ handle error
}
}
}
public static final boolean reload( ){
for( int i = 1; i <= 4; i++ ){
String sURL = "c:\\xyz.com\\" + i; \\ URL I am reading from
System.out.println( "retrieving data from:\n" + sURL );
StringBuffer sb = new StringBuffer( 10000 );
try {
URL url = new URL( sURL );
HttpURLConnection con = (HttpURLConnection) url.openConnection();
sb = readStream( con.getInputStream() );
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
System.out.println( sb.toString() );
}该任务尝试建立多个URL连接,并打印出每个URL连接的响应。在实践中发生的情况是“从...检索数据”消息出现一次,则该任务显示为挂起。如果我通过在StdIn中键入命令来使用REPL,那么在标准输出中就会出现"connection timed out“错误。
因此,TimerTask似乎与REPL (在readline上阻塞)有冲突。这是怎么回事?
发布于 2016-02-10 00:38:51
java.util.TimerTask只有运行任务的线程。如果一个任务继续运行,其他任务必须等待,直到它完成。你可以用java.util.concurrent.ScheduledExecutorService代替它,它可以启动更多的线程来运行任务……
我猜你尝试连接的URL需要一些“输入”,所以它在等待额外的数据……尝试修改源代码并为其提供一些数据。例如:
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(5000);//not required
con.setDoOutput(true);
con.setDoInput(true);
OutputStream out = con.getOutputStream();
out.write("¶m1=a¶m2=b".getBytes());
out.close();
sb = readStream( con.getInputStream() );发布于 2016-02-10 21:11:53
我最终发现了问题所在。Java方法的实现在一个名为streamHandlerLock的内部对象上进行同步,该对象由一组不同的内部HttpURLConnection库共享,包括缓冲的读取库。
这基本上意味着您不能在多个并发线程中使用使用java.net或java.io的任何基于流的IO。
在我的例子中,发生的情况是REPL阻塞了BufferedReader.readLine(),所以streamHandlerLock被冻结了。因此,当openConnection执行时,它会在这个对象上发生死锁。
(我可以在这里谈谈James Gosling的编码技巧,他设计和编写了这个拦截系统,并在源代码上签名,或者我可以说Sun Oak团队在16年前的2000年Java成为主流时重写这些垃圾代码的彻底失败,但我想我会让读者想象我可能会说什么。)
https://stackoverflow.com/questions/35296017
复制相似问题