在我的应用程序中,有一个单独的线程,每分钟由ScheduledExecutorService.scheduleAtFixedRate()
运行,它解析来自多个网站的RSS源。我正在使用Apache HttpClient接收xml。
示例代码:
InputStream inputStream = HTTPClient.get(url);
String xml = inputStreamToString(inputStream, encoding, websiteName);
public static String inputStreamToString(InputStream inputStream, String encoding, String websiteName)
{
BufferedReader bufferedReader = null;
PrintWriter printWriter = null;
StringBuilder stringBuilder = new StringBuilder();
int letter;
try
{
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, encoding));
printWriter = new PrintWriter(new File("src/doclog/"
+ websiteName + "_"
+ new SimpleDateFormat("MM_dd_yyyy_hh_mm_ss").format(new Date(System.currentTimeMillis()))
+ "_" + encoding + ".txt"), encoding);
while((letter = bufferedReader.read()) != -1)
{
char character = (char) letter;
printWriter.print(character);
stringBuilder.append(character);
}
}
catch(IOException e)
{
throw new RuntimeException(e);
}
finally
{
try
{
if(bufferedReader != null)
{
bufferedReader.close();
}
if(printWriter != null)
{
printWriter.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
System.out.println("String built");
return stringBuilder.toString();
}
和HTTPClient类:
public class HTTPClient
{
private static final HttpClient CLIENT = HttpClientBuilder.create().build();
public static InputStream get(String url)
{
try
{
HttpGet request = new HttpGet(url);
HttpResponse response = CLIENT.execute(request);
System.out.println("Response Code: " + response.getStatusLine().toString());
return response.getEntity().getContent();
}
catch(IOException | IllegalArgumentException e)
{
throw new RuntimeException(e);
}
}
}
正如标题所说,有时bufferedReader.readLine()
有可能永远挂起。我在这个主题上看到了另一个答案,他们建议检查bufferedReader.ready()
是否返回true
。问题是有些网站会在false
中一直返回bufferedReader.ready()
,同时处理它们,但是它们解析得很好。
如何防止我的线程挂在bufferedReader.readLine()上?
如果重要,response.getStatusLine().toString()
始终会返回HTTP/1.1 200 OK
修改
我发现挂起时bufferedReader.ready()
实际上是true
。
编辑2
BufferedReader.read()
也挂了。奇怪的是,只有在处理一个网站时才会发生挂起,并且它的发生绝对是随机的。应用程序可以工作15个小时,接收数百个无问题的响应,或者在发布后10分钟内挂起。我已经开始将每个更新的所有字符写入单独的文件中,并发现没有什么特别的事情真的发生。 Xml读取只是在文档中间永远停止,最后一个字符是<p dir="ltr"&g
。更新了代码。
另外,值得注意的是,不能有任何未处理的异常,因为在我的ScheduledExecutorService.scheduleAtFixedRate()
可运行的最高级别我捕获Throwable
,并打印它的stackTrace。
答案 0 :(得分:1)
ready()
方法返回true
,告诉您有可供阅读的字符。问题是readLine()
阻塞,直到它在输入中找到行尾。
public String readLine() 抛出IOException
读取一行文字。一条线被认为是任何一条线终止的 换行(&#39; \ n&#39;),回车(&#39; \ r&#39;)或回车 然后立即换行。
当您从流中读取时,无法保证数据将进入行边界,因此readLine()
调用阻止。
您可以使用不会阻止的read
方法,但您必须自己检查EOL。
public int read(char [] cbuf,int off,int len)抛出IOException
将字符读入数组的一部分。
此方法实现相应读取的一般合约 Reader类的方法。作为额外的便利,它尝试 通过反复调用read来读取尽可能多的字符 底层流的方法。这种迭代读取一直持续到 以下条件之一成为现实:
The specified number of characters have been read, The read method of the underlying stream returns -1, indicating end-of-file, or The ready method of the underlying stream returns false, indicating that further input requests would block.
如果基础流上的第一次读取返回-1表示 end-of-file然后此方法返回-1。否则此方法返回 实际读取的字符数。
此外,您还必须从读取的字符重建线条。一次读取整行是不方便的,但必须这样做。