1
여러 스레드와 병렬로 HTTP 요청을 보낼 수있는 코드를 작성했습니다. 부모 스레드는 thread.join()을 사용하여 모든 자식 스레드가 완료 될 때까지 대기합니다. 하지만 내 코드에서 join()은 때때로 작동하지 않았습니다. 누군가 내 코드의 문제점을 지적 할 수 있습니까? 감사.Android에서 스레드 조인이 작동하지 않습니까?
D/:multiProcessRequest( 964): Thread 18 is still alive : RUNNABLE
D/:multiProcessRequest( 964): Thread 20 is still alive : RUNNABLE
을 :
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: [[email protected]
D/GetThread:run( 964): 17 - get executed
D/GetThread:run( 964): 17 - 9000 bytes read from ......
D/GetThread:run( 964): 17: [[email protected]
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: [[email protected]
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: [[email protected]
이 두 라인 아래 두 개의 스레드가 여전히) (가입 후 실행중인 것을 보여 주었다 :() 로그에서
/**
* @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를 실행 한 후 이러한 디버그 메시지를 보았다
로그를 볼 수 있으므로 안드로이드 시뮬레이터에서만 시도했습니다. JVM에서이 코드를 사용해 보자. – user256239
JVM에서 동일한 코드를 시도했지만 문제가 재현되지 않았습니다. 이상해. 적어도 Android 시뮬레이터에는 스레드 동기화 문제가있는 것 같습니다. 어쨌든, 감사합니다. – user256239
문제 없습니다. Android 에뮬레이터에 대한 버그를 신고해야합니다. –