在定时任务中为了加快处理速度,一般都会使用多线程处理业务。需要注意一下事项:

1. 定时任务是否允许上一个定时任务未结束,下一个定时任务可以启动,通过Scheduled中的配置在决定。

2. 主线程已经关闭,线程池中的线程还在运行问题。线程池的关闭方法问题

3. 定时任务有大量数据,导致服务无法停止问题。

4. 如何获取线程的处理结果

如下代码是示例,stop状态的使用和线程池shutdown的处理逻辑需要依据自己的业务来处理。

@PreDestroy

public void destory(){

stop = true;

}

//线程停止状态, 通过注解检测到服务器停止时修改stop状态

boolean stop = false;

//服务器启动后延迟1分钟执行,定时任务结束后延迟1分钟执行下一次

@Scheduled(initialDelay = 60*1000L, fixedDelay = 60*1000L)

public void scheduling(){

List dataList = new ArrayList<>();

for (int i = 0; i < 1000; i++) {

dataList.add("data_"+i);

}

int threadSize = 10;

ExecutorService esPool = Executors.newFixedThreadPool(threadSize);

//接收线程的完成时间 或者其他返回结果

CompletionService ecs = new ExecutorCompletionService(esPool);

ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(dataList);

logger.info("===============start {}==================", System.currentTimeMillis());

//启动线程时修改退出线程状态

stop = false;

for (int i = 0; i < threadSize; i++) {

ecs.submit(()->{

long count = 0;

//线程处理加try catch 防止抛出异常中断线程,可能会导致线程池中所有的线程都中断,无可用线程

try{

// !queue.isEmpty()比queue.size()>0效率高很多 .size() 是要遍历一遍集合的

while (!stop && !queue.isEmpty()){

String data = queue.poll();

//500 可以在60秒内完成处理,正常退出

//改成 1000 如果不使用下面的收集结果代码,60秒内无法处理完,会强制shutdown 抛出异常

Thread.sleep(1000L);

logger.info("data {} ok.",data);

count++;

}

}catch (Exception e){

logger.error("",e);

}

//这里范围线程处理的结果

return System.currentTimeMillis()+"_"+count;

});

}

//获取线程的返回结果 会阻塞主线程,直到线程池中所有的线程返回结果

/*try {

for (int i = 0; i < threadSize; i++) {

String threadTime = ecs.take().get();

logger.info("thread run ok time:{}"+threadTime);

}

} catch (InterruptedException e) {

e.printStackTrace();

}catch (ExecutionException e) {

e.printStackTrace();

}*/

//关闭线程池

try {

esPool.shutdown();

logger.info("esPoll shutdown:{}", DateUtil.format(new Date(),DateUtil.PATTERN_DEFAULT));

//线程池阻塞,到指定的时间退出,如果所有线程执行完成返回true 否则返回false

boolean await = esPool.awaitTermination(60*1000L,TimeUnit.MILLISECONDS);

logger.info("esPool.awaitTermination 1:{}, {}",await,DateUtil.format(new Date(),DateUtil.PATTERN_DEFAULT));

if(!await) {

stop = true;

await = esPool.awaitTermination(10*1000L,TimeUnit.MILLISECONDS);

logger.info("esPool.awaitTermination 2:{}, {}",await,DateUtil.format(new Date(),DateUtil.PATTERN_DEFAULT));

}

if(!await){

logger.info("wait 60s not stop, shutdownNow");

// 超时的时候向线程池中所有的线程发出中断(interrupted)。

// 让线程池中的所有线程立即中断。 会抛出异常

esPool.shutdownNow();

}

} catch (InterruptedException e) {

//awaitTermination方法被中断的时候也中止线程池中全部的线程的执行。

esPool.shutdownNow();

logger.error("awaitTermination",e);

}

logger.info("===============end {}==================", System.currentTimeMillis());

}

java定时任务中使用多线程_定时任务使用多线程注意事项相关推荐

  1. Java面试中,一些常见的有关多线程问题!

    面试作为入职的第一道门槛,其重要性不言而喻.对于从事IT的很多工作人员而言,对面试往往信心不足,毕竟在真实面试中,会遇到很多技术问题,万一哪块技术点不熟,就会与心仪的offer失之交臂.接下来,小千以 ...

  2. java 线程中创建线程_如何在Java 8中创建线程安全的ConcurrentHashSet?

    java 线程中创建线程 在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为Concurren ...

  3. java编写的王八程序_利用JAVA多线程技术模拟龟兔赛跑.doc

    利用JAVA多线程技术模拟龟兔赛跑 摘要:该文介绍了利用JAVA语言的多线程技术,对"龟兔赛跑"寓言故事的模拟.从模拟程序的具体设计思路,到详细的实现过程,将技术的应用融入到一个有 ...

  4. 不属于JAVA类中的变量_在Java中,不属于整数类型变量的是( )。_学小易找答案...

    [单选题]整型数据类型中,需要内存空间最少的是( ). [单选题]下列语句序列执行后,i的值是( ). int i=16; do { i/=2; } while( i > 3 ); [填空题]布 ...

  5. java分页中显示更多_早期更多失败– Java 8

    java分页中显示更多 快速失败或早期失败是一种软件工程概念,旨在通过在不应该发生的事情发生时立即停止执行来防止复杂问题的发生. 在之前的博客文章和演示中,我将详细介绍这种方法的优点,在此博客文章中, ...

  6. 去掉java文件中的注释_利用JavaParser去除java文件中的注释

    利用JavaParser去除java文件中的注释 个人博客:记录一下在项目实施过程中的一些点 情景回顾 之前项目有个需求,就是去掉.java文件中的所有注释,常用的方法是用正则匹配.然而在网络上查找到 ...

  7. java文件中获取创建日期_如何在Java中获取文件的上次修改日期

    java文件中获取创建日期 Sometimes we need to get the file last modified date in Java, usually for listeners li ...

  8. java程序中语句隔开_《Java语言程序设计》填空题.doc

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspJava <Java语言程序设计>填空题.doc9页 ...

  9. java线程中的常用方法_[多线程] 线程中的常用方法-最详细

    线程中常用的方法 1.public void start() 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 2.public void run() 如果该线程是使用独立的 Runna ...

最新文章

  1. 实战Gradle——第一部分 Gradle介绍
  2. oracle tns连接拒绝,TNS-12564: TNS: 拒绝连接(new)
  3. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )
  4. mysql可视化工具-navicat的下载和使用
  5. mysql 如何删除重复的行_如何从mysql中的表中删除重复的行
  6. 在Eclipse中如何让struts.xml显示提示
  7. little w and Segment Coverage(差分)
  8. hadoop简单介绍_Hadoop:简单介绍
  9. Java Bootstrap:Dropwizard与Spring Boot
  10. 界面设计方法 (2) — 4.界面设计的原则与标准
  11. 绑定方法与非绑定方法
  12. Java读取word中表格
  13. 新手学appium-Appium for Windows说明(中文翻译)
  14. NameError: name ‘os‘ is not defined - 解决
  15. sis9280触摸ic 基于rk3288 的安卓4.4的 多点触摸
  16. Springboot2.2对put,detele方法的更改
  17. Redmine安装与入门指南
  18. 升级mac系统正在计算机,Mac升级卡死解决办法
  19. excel合并单元格和左对齐
  20. 商业周刊:苹果新CEO需打造强有力管理团队

热门文章

  1. Long-term 3D Localization and Pose from Semantic Labellings
  2. 百度云加速CDN配置
  3. Nano 10GX—AD模块如何采集模拟量数据
  4. 如何建造一个虚拟帝国?感官世界与人机交互需完美配合
  5. AcWing 1127 香甜的黄油
  6. 文本(文章内容)编辑器(CMS管理)
  7. 国庆,几家欢喜几家愁
  8. 微商的微信营销互动方法
  9. ext4 extent详解2之内核源码详解
  10. PostgreSQL 数据库下载安装