线程加入在Android中不起作用?

时间:2010-01-21 22:32:48

标签: java android

我编写的代码可以使用多个线程以并行方式发送http请求。父线程使用thread.join()等待所有子线程完成。但在我的代码中,join()有时不起作用。有人能指出我的代码有什么问题吗?感谢。

/**
 * @param urlSet
 *            , a set of link URLs (Can not be null)
 * @return Map<link URL, response in byte array>
 * @throws InterruptedException
 */
protected Map<String, byte[]> multiProcessRequest(Set<String> urlSet)
        throws InterruptedException {

    if (urlSet.isEmpty()) {
        return null;
    }

    // Create and initialize HTTP parameters
    HttpParams params = new BasicHttpParams();
    ConnManagerParams.setMaxTotalConnections(params, MAX_CONNECTIONS);
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

    // Create and initialize scheme registry
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), 80));

    // Create an HttpClient with the ThreadSafeClientConnManager.
    // This connection manager must be used if more than one thread will
    // be using the HttpClient.
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params,
            schemeRegistry);
    m_httpClient = new DefaultHttpClient(cm, params);

    List<String> urlList = new ArrayList<String>(urlSet);

    // create a thread for each URI
    GetThread[] threads = new GetThread[urlSet.size()];

    for (int i = 0; i < threads.length; i++) {
        HttpGet httpget = new HttpGet(urlList.get(i));
        threads[i] = new GetThread(m_httpClient, httpget, i + 1);
    }

    // start the threads
    for (int j = 0; j < threads.length; j++) {
        threads[j].start();
    }

    // join the threads
    for (int j = 0; j < threads.length; j++) {
        threads[j].join();
    }

    // FIXME: debug for statement only
    for (int j = 0; j < threads.length; j++) { 
        if (threads[j].isAlive()) {
            s_logger.debug("Thread " + (j+1) + " is still alive : " + threads[j].getState()); 
        }
    }

    // When HttpClient instance is no longer needed,
    // shut down the connection manager to ensure
    // immediate deallocation of all system resources
    m_httpClient.getConnectionManager().shutdown();

    s_logger.debug("ConnectionManager shutted down.");

    /* Prepare the return. */
    Map<String, byte[]> urlToResponseMap = new HashMap<String, byte[]>(
            threads.length);

    for (int i = 0; i < threads.length; ++i) {
        urlToResponseMap.put(urlList.get(i), threads[i].getResult());
    }

    return urlToResponseMap;
}

/**
 * A thread that performs a GET.
 */
static class GetThread extends Thread {

    private final HttpClient httpClient;
    private final HttpContext context;
    private final HttpGet httpget;
    private final int internalId;

    /** The response result of the URL get. */
    private byte[] result;

    public GetThread(HttpClient httpClient, HttpGet httpget, int id) {
        this.httpClient = httpClient;
        this.context = new BasicHttpContext();
        this.httpget = httpget;
        this.internalId = id;
    }

    public byte[] getResult() {
        return result;
    }

    /**
     * Executes the GetMethod and prints some status information.
     */
    @Override
    public void run() {

        s_logger.debug(internalId + " - about to get something from "
                + httpget.getURI());

        try {

            // execute the method
            HttpResponse response = httpClient.execute(httpget, context);

            s_logger.debug(internalId + " - get executed");

            // get the response body as an array of bytes
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toByteArray(entity);

                s_logger.debug(internalId + " - " + result.length
                        + " bytes read from " + httpget.getURI());
                s_logger.debug(internalId + ": " + result);
            }

        } catch (Exception e) {
            httpget.abort();
            s_logger.error(internalId + " - error: ", e);
        }
    }

}

在日志中,我在运行multiProcessRequest()后看到了这些调试消息:

D/GetThread:run(  964): 16 - get executed
D/GetThread:run(  964): 16 - 9444 bytes read from ......
D/dalvikvm(  964): GC freed 675 objects / 463256 bytes in 84ms
D/GetThread:run(  964): 16: [B@4383add8
D/GetThread:run(  964): 17 - get executed
D/GetThread:run(  964): 17 - 9000 bytes read from ......
D/GetThread:run(  964): 17: [B@437f5240
D/GetThread:run(  964): 18 - get executed
D/:multiProcessRequest(  964): Thread 18 is still alive : RUNNABLE

D/:multiProcessRequest(  964): Thread 20 is still alive : RUNNABLE
D/dalvikvm(  964): threadid=17 wakeup: interrupted

D/:multiProcessRequest(  964): ConnectionManager shutted down.

D/GetThread:run(  964): 18 - 9427 bytes read from ......
D/$GetThread:run(  964): 18: [B@438412e8
D/dalvikvm(  964): GC freed 1269 objects / 666456 bytes in 90ms
W/ExpatReader(  964): DTD handlers aren't supported.
D/$GetThread:run(  964): 20 - get executed
D/$GetThread:run(  964): 20 - 12751 bytes read ......
D/$GetThread:run(  964): 20: [B@43836dc0

以下这两行表明在join()之后仍有两个线程在运行:

D/:multiProcessRequest(  964): Thread 18 is still alive : RUNNABLE

D/:multiProcessRequest(  964): Thread 20 is still alive : RUNNABLE

1 个答案:

答案 0 :(得分:1)

嗯......,你的代码对我来说很好看,我看不到你的联接之后有什么线程可以存活。除非join抛出异常,但在这种情况下,你的日志记录语句不会触发。

您是否在其他JVM或平台上尝试过此操作?