文章目录
- 业务场景:
- 导入文件,要处理文件中一堆数据,为了用户体验只能导入后立马返回上传成功,实际则是直接先记录导入状态(处理中),然后线程池处理完把状态改为处理完成
-
- 上传文件,将文件存放进自己dfs文件系统,拿到地址url链接,然后生成一个任务id在数据库表中记录及该地址url, 把新建的任务id放入本地缓存ConcurrentLinkedQueue中
-
- 往线程池中扔线程任务异步处理业务, 异步处理线程任务,任务从本地缓存ConcurrentLinkedQueue中获取表数据的任务id从而获取该文件的url地址,拿到该文件的数据,然后遍历文件数据进行业务处理,处理完毕则更新数据库状态为处理成功或处理失败
线程池
- 定义线程池,调用方法execute将线程任务扔进去
public class BossThreadFactory {
public static ThreadPoolExecutor threadPoolExecutor;
static {
int corePoolSize = 2;
threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, 2, 1, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(20), new ThreadFactoryBuilder().setNameFormat("boss-%d").build(),
new ThreadPoolExecutor.AbortPolicy());
}
public static void execute(Runnable runnable){
threadPoolExecutor.execute(runnable);
}
}
线程任务
@Component
public class NumberStateThread extends Thread {
private static final Logger logger = LoggerFactory.getLogger(NumberStateThread.class);
// 存放导入文件的任务id
public static ConcurrentLinkedQueue threadLinkedQueue = new ConcurrentLinkedQueue<>();
@Override
public void run() {
// 往本地缓存队列拿出数据
Integer taskId = threadLinkedQueue.poll();
//处理后续业务
}
}
实战(参考即可)
@Autowired
private NumberStateThread numberStateThread;
@Override
public Result uploadFile(MultipartFile file) throws Exception {
//往本地缓存队列放入数据
boolean offerB = NumberStateThread.threadLinkedQueue.offer(mobileTypeState.getId());
if (offerB) {
logger.info("【checkStateNumberUpload】将任务ID[{}]放入本地缓存队列成功", mobileTypeState.getId());
//将线程任务放进线程池执行
BossThreadFactory.execute(numberStateThread);
}
}