Java BufferedReader.readLine()会阻塞一段时间

Java BufferedReader.readLine()会阻塞一段时间,java,android,tcp,bufferedreader,Java,Android,Tcp,Bufferedreader,我试图获取一个http响应字符串(只是一个JSON对象),有时这段代码会无限期地等待 line=reader.readLine() 可能是,这种行为的原因是坏的互联网连接(我使用3G调制解调器),但我需要一个稳定的解决方案,以避免这种无限锁定。这里可以做些什么来避免它 HttpResponse response = httpClient.execute(httpPost); InputStream content = null; JSONObject json_obj; if (respons

我试图获取一个http响应字符串(只是一个JSON对象),有时这段代码会无限期地等待

line=reader.readLine()

可能是,这种行为的原因是坏的互联网连接(我使用3G调制解调器),但我需要一个稳定的解决方案,以避免这种无限锁定。这里可以做些什么来避免它

HttpResponse response = httpClient.execute(httpPost);

InputStream content = null;
JSONObject json_obj;
if (response.getStatusLine().getStatusCode() == 200) {
    HttpEntity entity = response.getEntity();

    try {
        content = entity.getContent();

        BufferedReader reader = new BufferedReader(new InputStreamReader(content, "UTF-8"), 256);
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (Exception e) {}
}

您可以指定读取超时:

HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);
应将读取超时设置为30秒。 可能还需要指定连接超时:

client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
或者任何网络/IO都应该在后台线程中完成,以防止主线程被锁定

如果你在安卓4.0+上测试你的代码,你还会看到主线程上不再允许联网,并且会抛出一个异常


看看哪种方法是在后台线程上运行此类任务的简单、无痛苦的方法。

避免“无限”锁定的一个好方法是在单独的线程中执行此http调用,并使用处理程序,注意主线程已加载信息,并且可以按照您的需要使用它

下面是我自己使用SaxParser的一个示例:

public void SearchFromSuperClass(String text)
{   
    mHandler = new Handler();
    Thread t = new Thread(){
        public void run() {
            try {
              String strurl="URLTOPATH";
              URL url = new  URL(strurl);
              SAXParserFactory factory = SAXParserFactory.newInstance();

              SAXParser parser = factory.newSAXParser();
              FundsHandlerRanking handler = new FundsHandlerRanking();
              parser.parse(url.openConnection().getInputStream(), handler);
              search_response = handler.getrankings();


              mHandler.post(mUpdateResults);
            } catch (Exception e) {
                search_response = null;
                mHandler.post(mUpdateResults);

            }

        }
    };

    t.start();
}
final Runnable mUpdateResults = new Runnable() {
    public void run() {
        updateResultsInUi();
    }
};

private void updateResultsInUi() {

    try
    {
        if(search_response != null)
        {
            lview.setAdapter(new SearchRankingAdapter(mycontext, search_response, false));
        }
        Pdialog.dismiss();
    }
    catch (Exception e) {
        lview.setAdapter(null);
        if (Pdialog.isShowing())
        {
            Pdialog.dismiss();
        }
    }
}
使用mHandler.post(…)可以将调用放入要发送到主UI线程的队列中,在那里,可以毫无问题地修改UI对象(不能修改主线程之外的UI对象)


希望这有助于

你可以在一个单独的线程中执行<代码> ReadRead()/Case>的内容,当你想杀死所有的(以及最重要的是怎样)的时候,你会考虑避免网络查询是非阻塞的吗?(还有,EntityUtils.toString做的和你在1行中做的一样)@fiddler我已经在后台线程中做了,问题只是关于阻塞。@njzk2非常感谢,伙计!这是最好的解决方案:)@njzk2也是关于阻塞的。问题是,当请求已经发送到服务器并且服务器已经响应时,就会发生阻塞,但响应从未收到,也没有完全收到,线程什么也不等待。所以超时是件好事,只是不知道如何设置它。有一个很好的选择,将超时作为http调用参数。我已经在后台线程中这样做了,问题只是关于阻塞。
public void SearchFromSuperClass(String text)
{   
    mHandler = new Handler();
    Thread t = new Thread(){
        public void run() {
            try {
              String strurl="URLTOPATH";
              URL url = new  URL(strurl);
              SAXParserFactory factory = SAXParserFactory.newInstance();

              SAXParser parser = factory.newSAXParser();
              FundsHandlerRanking handler = new FundsHandlerRanking();
              parser.parse(url.openConnection().getInputStream(), handler);
              search_response = handler.getrankings();


              mHandler.post(mUpdateResults);
            } catch (Exception e) {
                search_response = null;
                mHandler.post(mUpdateResults);

            }

        }
    };

    t.start();
}
final Runnable mUpdateResults = new Runnable() {
    public void run() {
        updateResultsInUi();
    }
};

private void updateResultsInUi() {

    try
    {
        if(search_response != null)
        {
            lview.setAdapter(new SearchRankingAdapter(mycontext, search_response, false));
        }
        Pdialog.dismiss();
    }
    catch (Exception e) {
        lview.setAdapter(null);
        if (Pdialog.isShowing())
        {
            Pdialog.dismiss();
        }
    }
}