Spring RestTemplate正确的多线程使用

时间:2012-07-05 14:40:13

标签: android spring jackson

我尝试运行几个请求做不同的服务器和调试程序行为。首先,我创建并运行几个asynctasks,它们提出了几个请求

public class MyTask extends AsyncTask<Object, Void, Void> {
    int runnnigDownloadThreadsCount = 0;

    @Override
    protected Void doInBackground(Object... params) {
        runnnigDownloadThreadsCount++;
        try {
            // TODO здесь необходимо исправить serverName на оригинальный урл с указанием параметра сервера
            List<TravelTicket> ticketsList = TravelTicket.downloadTickets((TravelTicket.RequestServerParams) params[0], (String) params[1]);
            if (ticketsList != null)
                synchronized (TravelBookingApplication.travelTicketsList) {
                    TravelBookingApplication.travelTicketsList.addAll(ticketsList);
                }
            return null;
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    @Override
    protected void onPostExecute(Void result) {
        runnnigDownloadThreadsCount--;
        if (runnnigDownloadThreadsCount == 0) {
            Intent i = new Intent(getActivity().getApplicationContext(), HotelsAndTicketsResponseListActivity.class);
            i.putExtra("requestType", "tickets");
            getActivity().startActivity(i);
            if (dialog != null)
                dialog.dismiss();
        }
    }
}

    String[] urls = new String[]{
            "http://dl.dropbox.com/u/34053723/provider1.json"
            ,
            "http://dl.dropbox.com/u/34053723/provider2.json",
            "http://dl.dropbox.com/u/34053723/provider3.json",
            "http://dl.dropbox.com/u/34053723/provider4.json"
    };
    for (final String serverName : urls) {
        // TODO ЗАМЕНИТЬ!!!
        // for (final String serverName : params.serverNames) {
        new MyTask().execute(params, serverName);
    }

接下来在函数TravelTicket.downloadTickets(...)中我使用RestTemplate加载数据

public static ArrayList<TravelTicket> downloadTickets(RequestServerParams requestServerParams, String serverName) throws Exception {
    // Запрос к серверу с указанием конретного провайдера и идентификторов запроса

    // Заголовки
    HttpHeaders requestHeaders = new HttpHeaders();

    requestHeaders.setUserAgent(TravelBookingApplication.USER_AGENT);

    HttpEntity requestEntity = new HttpEntity(requestHeaders);
    RestTemplate restTemplate = new RestTemplate();

每个线程都接近最后一行HttpEntity requestEntity = new HttpEntity(requestHeaders);但是在第一次运行之后,调试器会冻结。看起来它在断点处停止但没有人。

1 个答案:

答案 0 :(得分:3)

我不确定发生了什么(没有足够的信息)但是我可以肯定地告诉你RestTemplate是线程安全的并且被设计为一次配置并在线程之间共享,这是与所有弹簧*Template对象一致。

这个声明在几个地方得到了spring 4.0文档的支持。

Section 11.6.1 Using the TransactionTemplate

  

TransactionTemplate采用与其他Spring模板(如JdbcTemplate)相同的方法。   ...   最后,TransactionTemplate类的实例是线程安全的

Section 13.2.1 JdbcTemplate best practices

  

一旦配置,JdbcTemplate类的实例就是线程安全的。

通过持久性,您可以找到关于JmsTemplate的类似陈述。关于RestTemplate documentation merely states

  

...它在概念上类似于Spring中的其他模板类,例如JdbcTemplate和JmsTemplate以及其他Spring组合项目中的其他模板类。

由此我推断出与其他核心模板类相同的方式是线程安全的。这当然意味着它不能保证是线程安全的,只要它不是,它就是一个bug。