ScheduledExecutorService任务将由多线程执行

时间:2018-11-13 02:59:16

标签: java spring multithreading rest scheduledexecutorservice

这让我感到非常好奇。有一个按钮可以通过ajax在jsp页面上发送一个简单的post请求,而我使用RESTFUL方法来处理该请求,但是该方法将被执行两次或三次。仅在CentOS 7.3上发生,在我使用Windows10的笔记本电脑上,不会发生多线程。我在Google上进行了搜索,但没有任何帮助  已找到。代码如下:

  

asset.jsp:

<button class="btn btn-default btn-sm" title="allDoMi">
      <i class="fa fa-arrow-down">allDoMi</i>
</button>
$("button[title='allDoMi']").click(function () {
    var dataparam = "version=1";
    if (!confirm('confirm all DoMi?'))
        return;
    //ajax request
    $.ajax({
        contentType: "application/json",
        url: serviceurl.baseurl + "/asset/doMiAction",
        data: dataparam,
        beforeSend: function () {
             //do nothing
        },
        error: function () {
             //do nothing
        },
        success: function (info) {
             //do nothing    
        }
    });
});
  

Asset.java

@Service
@Path("/asset")
public class AssetRest {
    @Path("/doMiAction")
    @POST
    @Produces({ MediaType.APPLICATION_JSON, 
                                 MediaType.APPLICATION_XML })
    public RestfulResult doMiAction(@FormParam("version") String 
          version) {
          logger.info("doMiAction method began....");
          //package data for duMiSyncDtos,here only for test
          List<DuMiSyncDto> duMiSyncDtos =new List<>();
          //this url is for http simulation using HttpURLConnection
          final String dumiUrl = "http://someip/someurl";
          final Map<String, List<DuMiSyncDto>> map; 
          //only continue when list is not empty
          if (!duMiSyncDtos.isEmpty()) {
             //this method used for sync data in a certain order
             map = groupList(duMiSyncDtos);
             SortedSet<String> ss = new TreeSet<>(map.keySet());
             final Iterator<String> iter = ss.iterator();
             final ScheduledExecutorService ticker = Executors.newSingleThreadScheduledExecutor();
             logger.info("NEW A SINGLETHREADSCHEDULEDEXECUTOR");
             //retrieve data from a .property file,I set it 20000,therefore the job will be executed in every 20 seconds
             final int DELAY = NumberUtils.toInt(WebUtils.getConfigValue("dumi.delay"));
             ticker.scheduleWithFixedDelay(new Runnable() {
             private int count;
             public void run() {
                logger.info("BEGIN RUN METHOD:"+System.identityHashCode(AssetRest.this));
                if(iter.hasNext()) {
                    try {
                        List<DuMiSyncDto> value = map.get(iter.next());
                        //this method used for simulating a httprequest using HttpURLConnection to invoke a remote service to get the result info which forms in a JSON string format
                        String resultmsg = getDuMiReturnMessage(dumiUrl,value);
                        if(resultmsg!=null && !resultmsg.contains("\"code\":\"0000\"")) {
                            logger.info("Return code is "+resultmsg+",the sync work will be terminated.");
                            ticker.shutdown();
                            return;
                        }
                        //this method used for showing some useful infomation on the console using log4j
                        showSyncInfomation(value);
                        //this method used for count how many items have been synchronized successfully
                        int currentcount = getSyncCount(resultmsg);
                        count += currentcount ;
                        logger.info("current sync  data:"+currentcount+",summing data"+count+"");
                    } catch (Exception e) {
                        logger.error("method[doMiAction]...executing schedule:",e);
                    }
                } else {
                    ticker.shutdown();
                }
            }
        }, 0, DELAY, TimeUnit.MILLISECONDS);
    }
}

单击按钮后,所有日志信息将在Putty控制台上显示两次或三次,但是我只单击一次该按钮!我已经测试了好几次,但是会发生,但是在Windows上我的笔记本电脑,这根本不会发生。这里有一个细节可能会有所帮助:以前定时执行的实现不是这样,它的编写方式是:

for(DuMiSyncDto dto:duMiSyncDtoList){
    //do the business code
    Thread.sleep(20000);
}

由于远程服务存在数据库同步,因此我需要控制每两个操作之间的间隔时间不要太快:每20秒执行一次,一次执行100个数据。在这种情况下,会发生多线程问题,我认为可能是因为for循环引起的,所以我改用JDK API更改了方式,但问题仍然存在。所以为什么所有这些?

---------------------------首次编辑------------------ ------------------------

private int getSyncCount(String resultmsg) {
    int count = 0;
    JSONObject obj = JSONObject.fromObject(resultmsg);
    String message = obj.getString("message");
    if(!WebUtils.isEmpty(message)) {
        String[] arr = message.split(" ");
        if(arr!=null && arr.length>1) {
            count += Integer.parseInt(arr[1].trim());
        }
    }
    logger.info("currentThreadName:"+Thread.currentThread().getName());
    return count;
}

注意此方法,我记录当前线程名称,它显示:

...     
currentThreadName:pool-1-thread-1
currentThreadName:pool-2-thread-1
currentThreadName:pool-3-thread-1
...

有3个线程时。

0 个答案:

没有答案