异步线程池与定时任务线程池:
两个线程池都是一样的步骤:
第一步是线程池配置;
第二步写具体定时或异步任务。
先看异步线程池:
package com.xnpool.common.async;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync // 启用异步任务
public class AsyncConfiguration {
@Value("${asynctask.corepoolsize}")
private int corepoolsize;
@Value("${asynctask.maxpoolsize}")
private int maxpoolsize;
@Value("${asynctask.queuecapacity}")
private int queuecapacity;
@Value("${asynctask.keepaliveseconds}")
private int keepaliveseconds;
@Value("${asynctask.threadnameprefix}")
private String threadnameprefix;
@Value("${asynctask.waitfortaskstocompleteonshutdown}")
private boolean waitfortaskstocompleteonshutdown;
@Value("${asynctask.awaitterminationseconds}")
private int awaitterminationseconds;
// 声明一个线程池(并指定线程池的名字)
@Bean("taskExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数5:线程池创建时候初始化的线程数
executor.setCorePoolSize(corepoolsize);
//最大线程数5:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setMaxPoolSize(maxpoolsize);
//缓冲队列500:用来缓冲执行任务的队列
executor.setQueueCapacity(queuecapacity);
//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
executor.setKeepAliveSeconds(keepaliveseconds);
//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
executor.setThreadNamePrefix(threadnameprefix);
/*
* 线程池对拒绝任务(无线程可用)的处理策略
* AbortPolicy:丢弃任务,直接抛出java.util.concurrent.RejectedExecutionException异常,默认的策略
* CallerRunsPolicy:这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功
* DiscardOldestPolicy: 丢弃队列最前面的任务,然后重新尝试执行任务,会导致被丢弃的任务无法再次被执行
* DiscardPolicy:抛弃当前任务;会导致被丢弃的任务无法再次被执行,但是不抛出异常
*/
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(waitfortaskstocompleteonshutdown);
executor.setAwaitTerminationSeconds(awaitterminationseconds);
executor.initialize();
return executor;
}
}
启用了线程异步任务后,就可以写代码了:
package com.xnpool.common.async;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xnpool.common.constant.AuthConstant;
import com.xnpool.common.mapper.ds1.CCoinMapper;
import com.xnpool.common.mapper.ds1.SubuserMapper;
import com.xnpool.common.mapper.ds2.UserAddressMapper;
import com.xnpool.common.model.CommonCoin;
import com.xnpool.common.model.Subuser;
import com.xnpool.common.model.UserAddress;
import com.xnpool.common.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AsyncTaskService {
@Autowired
private UserAddressMapper userAddressMapper;
@Autowired
private TableUtil tableUtil;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private CCoinMapper coinMapper;
@Autowired
private SubuserMapper subuserMapper;
@Autowired
private RedisService redisService;
/**
*
* @param pid 企业id
* @param aid 应用id
* @param uid 用户id
* @param cid 子账号id
*/
@Async("taskExecutor")//指定了异步线程池名
public void executeAsyncTask(Long pid,Long aid, String uid, String cid,boolean b) {
String sql="select coin_id as coinId,coin_name as coinName,price,contract_coin_id as contractCoinId,contract_coin as contractCoin from t_coin";
/*//查询币种列表 new BeanPropertyRowMapper<CommonCoin>(CommonCoin.class)*/
//BeanPropertyRowMapper<CommonCoin> rowMapper = new BeanPropertyRowMapper<CommonCoin>(CommonCoin.class);
List<CommonCoin> coinIds =coinMapper.selectList(new QueryWrapper<CommonCoin>());
ArrayList<UserAddress> userAddressArrayList = new ArrayList<UserAddress>();
String existsAddress = tableUtil.isExistsAddress(pid);//一个企业一个用户币种关联表。(没有表就先创建)
log.info("增加用户或子账户的币种地址============");
if (existsAddress != null && userAddressArrayList.size()>0) {
userAddressMapper.insertCoinBase(existsAddress, userAddressArrayList);
}
}
@Async("taskExecutor")//指定了异步线程池名
public void executeAsyncCoinTask(Integer coinId, String coinName,Integer isContact, Integer contactCoinId) {
List<Subuser> ulist=subuserMapper.findAllSubList();
if(CollectionUtil.isNotEmpty(ulist)){
Map<Long,List<Subuser>> map=ulist.stream().filter(u->u.getEnterpriseId()!=null).collect(Collectors.groupingBy(Subuser::getEnterpriseId));
Long platId=getPalateFromId();
String existsAddress = tableUtil.isExistsAddress(pid);//一个企业一个用户币种关联表。(没有表就先创建)
log.info("增加用户或子账户的币种地址============");
if (existsAddress != null && userAddressArrayList.size()>0) {
userAddressMapper.insertCoinBase(existsAddress, userAddressArrayList);
}
}
}
}
}
下面贴定时任务线程池:
package com.xnpool.admin.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduleExecutor());
}
@Bean(destroyMethod="shutdown")
public Executor taskScheduleExecutor() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("schedule_task-");
scheduler.setAwaitTerminationSeconds(600); 线程池关闭前最大等待时间,确保最后一定关闭
scheduler.setWaitForTasksToCompleteOnShutdown(true);// 线程池关闭时等待所有任务完成
return scheduler;
//return Executors.newScheduledThreadPool(10); //指定线程池大小
}
}
具体使用定时任务的地方:
@Slf4j
@Service
public class SendMessageService {
@Autowired
private PushUtil pushUtil;
@Autowired
private TransactionMapper transactionsMapper;
@Autowired
private TUserMapper userMapper;
@Autowired
private TCoinMapper coinMapper;
@Autowired
private TNoticeMapper noticeMapper;
@Autowired
private TMessageMapper messageMapper;
@Autowired
private TableUtil tableUtil;
@Autowired
private RedisService redisService;
/**
* 推送公告(把公告推送给所有手机用户,推送后,不管用户是否接收,公告状态改为已发送状态)
*/
@Scheduled(fixedDelay = 1000 * 60 * 5)
public void sendNotice() {
List<TNotice> notices = noticeMapper.selectList(new QueryWrapper<TNotice>().lambda().eq(TNotice::getIsSend,0));
if (notices != null && notices.size() > 0) {
List<Integer> idList = notices.stream().map(TNotice::getId).collect(Collectors.toList());
List<TUser> userList = userMapper.selectClientList();
List<String> clinetList=userList.stream().map(TUser::getClientid).collect(Collectors.toList());
}
}
/**
* 推送消息(将所有状态是已完成未发送的交易,发送给用户。 发送完就把状态改成已发送。)
*/
@Scheduled(fixedDelay = 1000 * 10)
public void sendTx() {
}
}
这两个定时任务没有指定线程池名字,但已确认它是在线程池ScheduleConfig 中。