Java 多线程(无状态类)

Java 多线程(无状态类),java,multithreading,stateless,Java,Multithreading,Stateless,很抱歉写了这么长的代码,但我想知道是否有人可以帮助解决多线程问题(我对多线程非常陌生)。我试图设计一个面向RESTFUL web服务API的facade类,该API可以与多个线程共享。我使用HttpURLConnection进行连接,使用googlegson进行JSON数据的转换 下面这节课是我到目前为止所学的。在本例中,它有一个公共方法来进行API调用(authenticateCustomer()),私有方法用于促进API调用(即构建POST数据字符串、发出POST请求等) 我创建了这个类的一

很抱歉写了这么长的代码,但我想知道是否有人可以帮助解决多线程问题(我对多线程非常陌生)。我试图设计一个面向RESTFUL web服务API的facade类,该API可以与多个线程共享。我使用HttpURLConnection进行连接,使用googlegson进行JSON数据的转换

下面这节课是我到目前为止所学的。在本例中,它有一个公共方法来进行API调用(authenticateCustomer()),私有方法用于促进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;
    }
}
QuizSyncAPIFacade公共期末班
{
//API连接详细信息
私有最终字符串m_apiDomain;
私有最终字符串m_apiContentType;
专用最终整数m_缓冲区大小;
//建设者
公共QuizSyncAPIFacade()
{
m_apiDomain=“http://*******************************”;
m_apiContentType=“.json”;
m_bufferSize=8192;//8k
}
私有字符串readInputStream(InputStream流)引发IOException
{
//为输入流创建缓冲区
字节[]缓冲区=新字节[m_bufferSize];
整数读取计数;
StringBuilder=新的StringBuilder();
而((readCount=stream.read(buffer))>-1){
append(新字符串(buffer,0,readCount));
}
返回builder.toString();
}
私有字符串buildPostData(HashMap postData)引发UnsupportedEncodingException
{
字符串数据=”;
for(Map.Entry:postData.entrySet())
{
数据+=(URLEncoder.encode(entry.getKey(),“UTF-8”)+“=”+URLEncoder.encode(entry.getValue(),“UTF-8”)+“&”);
}
//修剪最后一个字符(尾随符号和)
int length=data.length();
如果(长度>0){
data=data.substring(0,(长度-1));
}
返回数据;
}
私有字符串buildJSONError(字符串消息、字符串名称、字符串地址)
{
字符串错误=“{\'errors\”:[{\'message\':\'+message+“\”,\'name\':\'+name+“\”,\'at\':\'+at+“\”}];
返回误差;
}
私有字符串callPost(字符串url、HashMap postData)引发IOException
{
//设置API调用的URL
URL apiUrl=新URL(URL);
//构建post数据
字符串数据=buildPostData(postData);
//调用API操作
httpurl连接连接;
试一试{
conn=(HttpURLConnection)apirl.openConnection();
}捕获(IOE异常){
抛出新IOException(buildJSONError(“打开连接失败”,“连接失败”,“失败”);
}
//设置过帐数据的连接参数
conn.setRequestMethod(“POST”);
conn.SETUSECHACHES(假);
conn.setDoInput(真);
连接设置输出(真);
//写入post数据
试一试{
DataOutputStream wr=新的DataOutputStream(conn.getOutputStream());
wr.writeBytes(数据);
wr.flush();
wr.close();
}捕获(IOE异常){
抛出新的IOException(buildJSONError(“未能在输出流中发布数据(连接是否正常)”,“发布数据失败”,”);
}
//从服务器读取响应
输入流为;
试一试{
is=conn.getInputStream();
}捕获(IOE异常){
InputStream errStr=conn.getErrorStream();
如果(errStr!=null)
{
字符串errResponse=readInputStream(errStr);
抛出新IOException(errResponse);
} 
其他的
{
抛出新IOException(buildJSONError(“读取错误流失败(连接正常)”,“错误流失败”,”);
}
}
//从服务器读取并返回响应
返回readInputStream(is);
}
/* -------------------------------------
* 
*同步API调用
* 
------------------------------------- */
公共APIResponse authenticateCustomer(HashMap postData)
{
//设置此API调用的URL
字符串apiURL=m_apiDomain+“/customer/authenticate”+m_apiContentType;
Gson jsonConv=new Gson();
字符串apiResponse=“”;
尝试
{ 
//调用API操作
apirresponse=callPost(apirl,postData);
//将JSON响应转换为所需的对象类型
CustomerAuthentication customerAuth=jsonConv.fromJson(apiResponse,CustomerAuthentication.class);
//构建并返回API响应对象
APIResponse结果=新的APIResponse(true,customerAuth,null);
返回结果;
} 
捕获(IOE异常)
{
//生成并返回带有错误列表的故障的API响应对象
APIErrorList errorList=jsonConv.fromJson(e.getMessage(),APIErrorList.class);
APIResponse结果=新的APIResponse(假、空、错误列表);
返回结果;
}
}

}

如果您收到一个错误,可能是因为您过载了身份验证服务(如果您一次执行此操作,则不会发生这种情况),可能是因为它返回了一个错误,如500、503或504,您可能会忽略该错误,并且不会得到任何您期望的结果,您将返回
null

如果没有1000个CPU,我会使用更少的线程