gpt4 book ai didi

java - 是否同步 PoolingClientConnectionManager

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:13:03 26 4
gpt4 key购买 nike

在我的应用程序中,有多个 IntentService 根据用户与应用程序的交互以随机间隔与 Tomcat 服务器连接/通信。

我正在为 Http 使用以下 Singleton

public class CustomHttpClient { 
private static HttpClient customHttpClient;
/** A private Constructor prevents instantiation */
private CustomHttpClient() {
}

public static synchronized HttpClient getHttpClient() {
if (customHttpClient == null) {
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
HttpProtocolParams.setUserAgent(params,"Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83)" +
" AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
ConnManagerParams.setTimeout(params, 1000);
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 10000);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg);
customHttpClient = new DefaultHttpClient(conMgr, params);
}
return customHttpClient;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}

除了当两个 IntentService 同时尝试 Http 或者当一个连接正在进行并且另一个连接已建立时它会给出 connectTimeOut 之外,该类工作正常。 p>

代码中的一个明显改进是用 PoolingClientConnectionManager 替换弃用的 ThreadSafeClientConnManager

我应该在此处同步 -> public static synchronized HttpClient getHttpClient()

导致 connectTimeOut 的单例中有什么错误?

最佳答案

Synchronize the PoolingClientConnectionManager or not?

是也不是。如果您希望 getHttpClient() 成为单例(IMO 是个好主意),您必须使其线程安全。这需要 synchronized。如果没有 synchronized,两个线程可以同时进入 if block (因为 customHttpClient == null 对两个线程都是 true)并创建两个实例。

但是有更好的(和更快的)方法不用 synchronized 来创建线程安全的单例。我喜欢Singleton Holder例如方法。

但是无论您在这里使用的是什么单例,都不应该出现连接超时。如果您为每个线程使用新的 HttpClient 实例,它也应该可以工作。


如果发生连接超时,则您的线程之一无法在您使用 HttpConnectionParams.setConnectionTimeout(params, 5000); = 5 秒设置的时间限制内连接到服务器。

这可能有几个原因。例如,如果您的连接缓慢且不稳定,则可能需要更长的时间,因为您的连接可能会中断几秒钟。或者,如果您的服务器由于配置(例如每个 IP 的连接限制)或因为硬件无法处理更多连接而无法处理更多连接,您也会看到此问题。基本上任何阻止 HttpClient 向服务器发送数据包或从服务器接收数据包的事情都会触发该问题。意味着您的问题要么在设备上,要么在网络上,要么在服务器上。

我不知道您的网络设置,但您可以尝试增加超时时间,看看是否有任何效果。 AndroidHttpClient例如将这些超时设置为 60 秒。如果您使用的是 WiFi 且连接稳定,那么这远远超过要求,但在连接非常弱时也很好。

您还可以检查 AndroidHttpClient 应用的其他设置是否有帮助。

下面AndroidHttpClient的设置

// Default connection and socket timeout of 60 seconds.  Tweak to taste.
private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000;

// ---------------------------------------------------------------------- //
HttpParams params = new BasicHttpParams();

// Turn off stale checking. Our connections break all the time anyway,
// and it's not worth it to pay the penalty of checking every time.
HttpConnectionParams.setStaleCheckingEnabled(params, false);

HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
HttpConnectionParams.setSocketBufferSize(params, 8192);

// Don't handle redirects -- return them to the caller. Our code
// often wants to re-POST after a redirect, which we must do ourselves.
HttpClientParams.setRedirecting(params, false);

// Use a session cache for SSL sockets
SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context);

// Set the specified user agent and register standard protocols.
HttpProtocolParams.setUserAgent(params, userAgent);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https",
SSLCertificateSocketFactory.getHttpSocketFactory(
SOCKET_OPERATION_TIMEOUT, sessionCache), 443));

ClientConnectionManager manager =
new ThreadSafeClientConnManager(params, schemeRegistry);

return new DefaultHttpClient(manager, params);

要确定您的问题出在哪里,您可以查看您的服务器连接日志并检查设备是否尝试启动连接,如果是,是否存在连接未建立的原因。如果超时时您没有看到任何连接尝试,则很可能是设备或网络问题。

如果您可以访问设备所连接的网络 (=WiFi),您可以使用例如Wireshark由于连接尝试超时的原因。您可以在那里看到设备是否发送连接请求。

最后但同样重要的是,它可能是由您的某些代码引起的。如果您找不到其他解决方案,请尝试使用 HttpURLConnection 实现它,看看是否有帮助。

关于java - 是否同步 PoolingClientConnectionManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12030331/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com