gpt4 book ai didi

java - 多线程(无状态类)

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:33:55 25 4
gpt4 key购买 nike

对于长代码帖子表示歉意,但我想知道是否有人可以帮助解决多线程问题(我对多线程很陌生)。我正在尝试为可以与多个线程共享的 RESTFUL Web 服务 API 设计外观类。我正在使用 HttpURLConnection 进行连接,并使用 Google GSON 与 JSON 数据相互转换。

下面的类(class)是我目前所拥有的。在此示例中,它有一个公共(public)方法来进行 API 调用 (authenticateCustomer()),而私有(private)方法用于促进 API 调用(即构建 POST 数据字符串、发出 POST 请求等)。

我创建了这个类的一个实例并与 1000 个线程共享。线程调用 authenticateCustomer() 方法。大多数线程都可以工作,但有些线程会出现空指针异常,这是因为我没有实现任何同步。如果我使 authenticateCustomer() 方法“同步”,它就可以工作。问题是这会导致并发性较差(例如,POST 请求突然需要很长时间才能完成,这将阻塞所有其他线程)。

现在回答我的问题。下面的类不是无状态的,因此是线程安全的吗?类中的极少数字段被声明为 final 并在构造函数中分配。所有方法都使用局部变量。 Gson 对象是无状态的(根据他们的网站),无论如何在 API 方法中创建为局部变量。

public final class QuizSyncAPIFacade 
{
// API Connection Details
private final String m_apiDomain;
private final String m_apiContentType;
private final int m_bufferSize;

// Constructors
public QuizSyncAPIFacade()
{
m_apiDomain = "http://*****************************";
m_apiContentType = ".json";
m_bufferSize = 8192; // 8k
}

private String readInputStream(InputStream stream) throws IOException
{
// Create a buffer for the input stream
byte[] buffer = new byte[m_bufferSize];

int readCount;

StringBuilder builder = new StringBuilder();

while ((readCount = stream.read(buffer)) > -1) {
builder.append(new String(buffer, 0, readCount));
}

return builder.toString();
}

private String buildPostData(HashMap<String,String> postData) throws UnsupportedEncodingException
{
String data = "";

for (Map.Entry<String,String> entry : postData.entrySet())
{
data += (URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8") + "&");
}

// Trim the last character (a trailing ampersand)
int length = data.length();

if (length > 0) {
data = data.substring(0, (length - 1));
}

return data;
}

private String buildJSONError(String message, String name, String at)
{
String error = "{\"errors\":[{\"message\":\"" + message + "\",\"name\":\"" + name + "\",\"at\":\"" + at + "\"}]}";

return error;
}

private String callPost(String url, HashMap<String,String> postData) throws IOException
{
// Set up the URL for the API call
URL apiUrl = new URL(url);

// Build the post data
String data = buildPostData(postData);

// Call the API action
HttpURLConnection conn;

try {
conn = (HttpURLConnection)apiUrl.openConnection();
} catch (IOException e) {
throw new IOException(buildJSONError("Failed to open a connection.", "CONNECTION_FAILURE", ""));
}

// Set connection parameters for posting data
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);

// Write post data
try {
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(data);
wr.flush();
wr.close();
} catch (IOException e) {
throw new IOException(buildJSONError("Failed to post data in output stream (Connection OK?).", "POST_DATA_FAILURE", ""));
}

// Read the response from the server
InputStream is;

try {
is = conn.getInputStream();
} catch (IOException e) {
InputStream errStr = conn.getErrorStream();

if (errStr != null)
{
String errResponse = readInputStream(errStr);
throw new IOException(errResponse);
}
else
{
throw new IOException(buildJSONError("Failed to read error stream (Connection OK?).", "ERROR_STREAM_FAILURE", ""));
}
}

// Read and return response from the server
return readInputStream(is);
}

/* -------------------------------------
*
* Synchronous API calls
*
------------------------------------- */

public APIResponse<CustomerAuthentication> authenticateCustomer(HashMap<String,String> postData)
{
// Set the URL for this API call
String apiURL = m_apiDomain + "/customer/authenticate" + m_apiContentType;

Gson jsonConv = new Gson();

String apiResponse = "";

try
{
// Call the API action
apiResponse = callPost(apiURL, postData);

// Convert JSON response to the required object type
CustomerAuthentication customerAuth = jsonConv.fromJson(apiResponse, CustomerAuthentication.class);

// Build and return the API response object
APIResponse<CustomerAuthentication> result = new APIResponse<CustomerAuthentication>(true, customerAuth, null);

return result;
}
catch (IOException e)
{
// Build and return the API response object for a failure with error list
APIErrorList errorList = jsonConv.fromJson(e.getMessage(), APIErrorList.class);

APIResponse<CustomerAuthentication> result = new APIResponse<CustomerAuthentication>(false, null, errorList);

return result;
}
}

最佳答案

如果您遇到错误,可能是因为您使身份验证服务过载(如果您一次执行此操作,则不会发生这种情况)也许它会返回类似 500、503 或 504 的错误,您可能忽略并没有得到任何你期望的结果,你返回 null http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

假设你没有 1000 个 cpu,我会使用更少的线程,拥有这么多线程可能会更慢而不是更有效。

我还会检查您的服务是否每次都正确返回,并调查您获得 null 值的原因。

如果您的服务一次只能处理 20 个请求,您可以尝试使用 Semaphore 作为最后的手段。这可以用来限制并发请求的数量。

关于java - 多线程(无状态类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10447969/

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