使用的技術棧:
spring @Component註解
@Autowired資源注入
newFixedThreadPool固定大小的線程池
ReentrantLock同步鎖
CountDownLatch倒計時器,是一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。
HTTP表單請求
package com.zcy.job;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zcy.dao.NotifyMapper;
import com.zcy.model.Notify;
import com.zcy.utils.HttpClientHandler;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author zcy
* 定時通知任務
*/
@Component
public class NotifyJob/* implements SimpleJob */{
private static final Logger logger = LoggerFactory.getLoggerNotifyJob.class);
@Autowired
private NotifyMapper NotifyMapper;
private ExecutorService pool = Executors.newFixedThreadPool(10);
private ReentrantLock lock = new ReentrantLock(true);
/*@Override*/
public void execute() {
try {
logger.info("job begin");
//獲取同步鎖,5秒內獲取否則放棄執行任務
boolean flag = lock.tryLock(5, TimeUnit.SECONDS);
if (!flag) {
logger.info("Job not get the lock");
return;
}
//獲取需要通知的數據庫數據
List<Notify> tl = NotifyMapper.getNotifys();
if (CollectionUtils.isEmpty(tl)) {
logger.info("NotifyJob query no data");
return;
}
//加統計鎖等待所有線程執行完畢釋放同步鎖
CountDownLatch latch = new CountDownLatch(tl.size());
for (Notify t : tl) {
pool.execute(() -> {
try {
logger.info("NotifyJob begin handler uuid:{}",t.getLogId());
Map<String, String> param = JSON.parseObject(t.getNotifyStr(), Map.class);
String resultStr = HttpClientHandler.onRequestMap(param, t.getNotifyUrl(), "application/x-www-form-urlencoded");
logger.info("NotifyJob resultStr:{}", resultStr);
if (StringUtils.isNotEmpty(resultStr)) {
JSONObject result = JSON.parseObject(resultStr);
String code = result.getString("res_code");
if ("success".equals(code)) {
t.setResCode("S");
t.setResMsg(result.getString("res_msg"));
} else {
t.setResCode("F");
t.setResMsg(result.getString("res_msg"));
}
} else {
t.setResCode("F");
t.setResMsg(null);
}
logger.info("NotifyJob end handler uuid:{}",t.getLogId());
} catch (Exception e) {
logger.error("NotifyJob http error:", e);
t.setResMsg("system error");
t.setResCode("F");
}finally {
latch.countDown();
}
NotifyMapper.update(t);
});
}
latch.await(200,TimeUnit.SECONDS);//最大等待所有線程完成的時間
} catch (Exception e) {
logger.error("NotifyJob handler error, ",e);
}finally {
if (lock.isHeldByCurrentThread()){
lock.unlock();
}
}
logger.info("NotifyJob notify end");
}
}