一、ExecutorService 固定线程池 20个线程处理取最大时间作为并发结束时间
int poolSize = 20;
ExecutorService executor = Executors.newFixedThreadPool(poolSize);
List<Future<Boolean>> results = new ArrayList<>(poolSize);
try {
QueryRequest queryRequest = new QueryRequest();
queryRequest.setPage(1);
queryRequest.setPageSize(100);
Long endId = 100L;
Long startId = 10000L;
while (true) {
if (startId > endId) {
break;
}
//从startId 开始往后的一百个
queryRequest.setIdStart(startId + 1);
queryRequest.setIdEnd(startId + 100);
BasePageResult<QueryResponse> queryResponse = rpcClericService.queryGoods(queryRequest);
if (CollectionUtils.isEmpty(queryResponse.getResult())) {
log.info("no data not check can check startId {} ", startId);
startId = startId + 100;
continue;
}
for (QueryResponse item : queryResponse.getResult()) {
//开线程池
results.add(executor.submit(new Callable<Boolean>() {
@Override
public Boolean call() {
try {
//处理逻辑在这里
return true;
} catch (Exception e) {
log.error("checkJsonCanExchange UnboundOutGoods id {} error msg {}", item.getId(), e.getMessage());
return false;
}
}
}));
//线程池全部在运转直接等待处理完再来一批,这样20个线程用起来大约15个左右,不是最优
if (results.size() % poolSize == 0) {
for (Future<Boolean> me : results) {
try {
me.get().booleanValue();
} catch (Exception e) {
log.error("executor process result error {}", e.getMessage());
}
}
results.clear();
}
startId = item.getId() > startId ? item.getId() : startId;
}
}
if (results != null && !results.isEmpty()) {
for (Future<Boolean> me : results) {
try {
me.get().booleanValue();
} catch (Exception e) {
log.error("ExecutionException", e);
}
}
results.clear();
}
} catch (Exception e) {
log.error("SetStockGoodsStatusTask error {}", e.getMessage());
} finally {
if (executor != null) {
executor.shutdown();
}
}
一、ExecutorService 固定线程池 20个线程一直不停的处理类似消息消费 每台机器可以开着消费redis里面的任务,每个任务是有锁锁住的不会重复消费
private static final int concurrentSize = 20;
//阻塞队列20个
private static LinkedBlockingDeque<TaskInfo> taskQueue = new LinkedBlockingDeque<>(concurrentSize);
private static ExecutorService threadPoolConsumer = Executors.newFixedThreadPool(concurrentSize);
@Autowired
private RedisRepository redisRepository;
@Scheduled(fixedDelay = 1000L)
public void consumeTask() {
while (true) {
try {
Set<String> taskStrList = redisRepository.queryTaskFromSet(100L);
if (CollectionUtils.isEmpty(taskStrList)) {
return;
}
log.info("TaskManager query {} tasks", taskStrList.size());
for (String taskStr : taskStrList) {
String[] strList = taskStr.split(":");
Long taskId = Long.parseLong(strList[0]);
Long now = System.currentTimeMillis();
if (redisRepository.lockTask(taskId, now)) {
TaskInfo taskInfo = new TaskInfo(taskId, mallId);
taskInfo.setTaskLockTime(now);
redisRepository.removeTaskFromSet(taskId, mallId);
taskQueue.put(taskInfo);
}
}
} catch (Exception e) {
log.error("consume task failed", e);
}
}
}
@PostConstruct
public void init() {
//初始化让20个线程都跑起来 等待任务的到来
for (int i = 0; i < concurrentSize; i++) {
TaskManager.threadPoolConsumer.execute(() -> handleFunction());
}
}
private void handleFunction() {
while (true) {
TaskInfo taskInfo = null;
try {
// 空了会阻塞
taskInfo = taskQueue.take();
log.info("take task: " + JsonUtils.toJson(taskInfo));
StopWatch stopWatch = new StopWatch();
stopWatch.start(taskInfo.getTaskId().toString());
//处理逻辑在这里
stopWatch.stop();
Long executeTime = stopWatch.getTotalTimeMillis() / 1000L;
log.info("execute time {}", executeTime.toString());
} catch (Exception e) {
log.error("consume task fail: " + JsonUtils.toJson(taskInfo), e);
}
}
}