先回顾一下,Runnable 的使用方法。

package demo.knowledgepoints.scheduledtask.run;

/***
* 线程类
*/
public class ThreadTest implements Runnable { public static int ticket = 9; @Override
public void run() {
try {
System.out.println("当前线程:"+Thread.currentThread().getName());
while(true){
synchronized (this) {
Thread.sleep(1000L);
if (this.ticket > 0) {
ticket--;
System.out.println(Thread.currentThread().getName() + ":出售一张票!");
System.out.println("剩余票量:" + ticket);
} else {
System.out.println("没有票了!");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package demo.knowledgepoints.scheduledtask.run;

public class ThreadMemo {
public static void main(String[] args) {
ThreadTest threadTest1 =new ThreadTest();
new Thread(threadTest1).start();
new Thread(threadTest1).start();
}
}

每一个线程的启动,都会占用资源,一个线程5分钟执行一次,一个线程10分钟执行。两个线程分别启动则需要启动两个线程。线程越多需要启动的线程就越多。性能浪费就越大。

于是我们会考虑,5分钟的线程,我们5分钟到了去唤醒一个线程,执行一次,然后再让其睡眠,10分钟的线程也如初,就可以省下同一时间的线程数,线程越多效果越是明显。

正好:java提供了方法:ScheduledExecutorService

我们就根据ScheduledExecutorService来实现一个线程池:

package demo.knowledgepoints.scheduledtask.inf;

import demo.knowledgepoints.scheduledtask.iml.ScheduledTaskTot;

public interface ScheduledService {

    /**
* 添加一个任务
* @author Eric
* @date 16:14 2019/3/12
* @params runnable
* @params taskId
* @params initialDelay 初次等待 毫秒
* @params delay 间隔时间 毫秒(不延迟)
* @throws
* @return boolean
**/
boolean addFixedTask(ScheduledTaskTot scheduledTaskTot); /**
* 添加一个任务
* @author Eric
* @date 16:14 2019/3/12
* @params runnable
* @params taskId
* @params initialDelay 初次等待 毫秒
* @params delay 间隔时间 毫秒(延迟)
* @throws
* @return boolean
**/
boolean addTask(ScheduledTaskTot scheduledTaskTot); /**
* 修改一个任务
* @author Eric
* @date 16:14 2019/3/12
* @params runnable
* @params taskId
* @params initialDelay 初次等待 毫秒
* @params delay 间隔时间 毫秒
* @throws
* @return boolean
**/
boolean updateTask(ScheduledTaskTot scheduledTaskTot) throws InterruptedException; /**
* 移除一个任务
* @author Eric
* @date 16:14 2019/3/12
* @params taskId
* @throws
* @return boolean
**/
boolean remove(String taskId); /**
* 关闭定时任务服务
* @author Eric
* @date 16:14 2019/3/12
* @throws
* @return void
**/
void shutdown(); /**
* 初始化定时任务服务
* @author Eric
* @date 16:15 2019/3/12
* @throws
* @return void
**/
void init() throws Exception;
}
package demo.knowledgepoints.scheduledtask.inf;

public interface TaskServcesInf {

    public void Test1();
public void Test2();
public void Test3();
}
package demo.knowledgepoints.scheduledtask.iml;

import demo.knowledgepoints.scheduledtask.inf.ScheduledService;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; public class ScheduledServiceIml implements ScheduledService { private static ScheduledExecutorService service; private static Map<String, ScheduledFuture> futureMap = new ConcurrentHashMap<>(); @Override
public boolean addFixedTask(ScheduledTaskTot scheduledTaskTot) {
if (futureMap.get(scheduledTaskTot.getTaskId()) != null) {
return false;
}
// 这里将任务放入定时服务中
ScheduledFuture<?> scheduledFuture = service.scheduleAtFixedRate(scheduledTaskTot.getRunnable()
, scheduledTaskTot.getInitialDelay(), scheduledTaskTot.getDelay(), TimeUnit.MILLISECONDS); futureMap.put(scheduledTaskTot.getTaskId(),scheduledFuture);
return true;
} @Override
public boolean addTask(ScheduledTaskTot scheduledTaskTot) {
if (futureMap.get(scheduledTaskTot.getTaskId()) != null) {
return false;
}
// 这里将任务放入定时服务中
ScheduledFuture<?> scheduledFuture = service.scheduleWithFixedDelay(scheduledTaskTot.getRunnable()
, scheduledTaskTot.getInitialDelay(), scheduledTaskTot.getDelay(), TimeUnit.MILLISECONDS); futureMap.put(scheduledTaskTot.getTaskId(),scheduledFuture); return true;
} @Override
public boolean updateTask(ScheduledTaskTot scheduledTaskTot) throws InterruptedException {
if (futureMap.get(scheduledTaskTot.getTaskId()) == null) {
return false;
}
// 先停止
remove(scheduledTaskTot.getTaskId()); // 再添加
addTask(scheduledTaskTot);
return true;
} @Override
public boolean remove(String taskId) {
if (futureMap.get(taskId) == null) {
return false;
}
ScheduledFuture scheduledFuture = futureMap.get(taskId);
scheduledFuture.cancel(false);
futureMap.remove(taskId);
return true;
} @Override
public void shutdown() {
service.shutdown();
} @Override
public void init() throws Exception {
service = Executors.newScheduledThreadPool(8);
}
}
package demo.knowledgepoints.scheduledtask.iml;

import demo.untils.StringUntil;
import demo.untils.TimeUtil; import java.lang.reflect.Method; public class ScheduledTaskTot { /** 需要执行方法的线程 */
Runnable runnable;
/** 唯一的id用于增删改 */
String taskId;
/** 定时任务需要执行的方法类 */
String className;
/** 定时任务需要执行的方法 */
String method;
/** 首次执行等待时间 */
long initialDelay;
/** 间隔时间 */
long delay; /**
* 创建一个需要定时的任务
* @param taskId
* @param className
* @param method
* @param initialDelay
* @param delay
* @param beginTime(执行开始时间)
* @param endTime(执行结束时间)
*/
public ScheduledTaskTot(String taskId, String className, String method, long initialDelay, long delay, String beginTime, String endTime) {
this.taskId = taskId;
this.className = className;
this.method = method;
this.initialDelay = initialDelay;
this.delay = delay;
// 在创建实例的时候,初始化线程类,通过反射获取要执行的类与方法,目前没有加参数,大家可以自行扩展
runnable = () -> {
System.out.println("---------------------------------");
try {
//在beginTime 到 endTime 之间才执行。
if(StringUntil.isNotBlank(beginTime) && StringUntil.isNotBlank(endTime)){
if(TimeUtil.getTimeMillis(beginTime) - System.currentTimeMillis() >= 0 && TimeUtil.getTimeMillis(endTime) - System.currentTimeMillis() <= 0){
Class<?> cls = Class.forName(className);
Method method1 = cls.getMethod(method);
method1.invoke(cls.newInstance(),null);
}
}else{
Class<?> cls = Class.forName(className);
Method method1 = cls.getMethod(method);
method1.invoke(cls.newInstance(),null);
}
} catch (Exception e) {
e.printStackTrace();
}
};
} public Runnable getRunnable() {
return runnable;
} public void setRunnable(Runnable runnable) {
this.runnable = runnable;
} public String getTaskId() {
return taskId;
} public void setTaskId(String taskId) {
this.taskId = taskId;
} public String getClassName() {
return className;
} public void setClassName(String className) {
this.className = className;
} public String getMethod() {
return method;
} public void setMethod(String method) {
this.method = method;
} public long getInitialDelay() {
return initialDelay;
} public void setInitialDelay(long initialDelay) {
this.initialDelay = initialDelay;
} public long getDelay() {
return delay;
} public void setDelay(long delay) {
this.delay = delay;
}
}
package demo.knowledgepoints.scheduledtask.iml;

import demo.knowledgepoints.scheduledtask.inf.TaskServcesInf;

public class TaskServcesIml implements TaskServcesInf {

    public void Test1(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Test1------------------------");
}
public void Test2(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Test2------------------------");
} public void Test3(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Test3------------------------");
}
}
package demo.knowledgepoints.scheduledtask.iml;

public class ScheduledServiceTest {

    public static void main(String[] args) {
ScheduledServiceIml scheduledServiceIml = new ScheduledServiceIml();
try {
scheduledServiceIml.init();
scheduledServiceIml.addTask(new ScheduledTaskTot("T0001","demo.knowledgepoints.scheduledtask.iml.TaskServcesIml","Test1",1000L,5000L,null,null));
scheduledServiceIml.addTask(new ScheduledTaskTot("T0002","demo.knowledgepoints.scheduledtask.iml.TaskServcesIml","Test2",1000L,5000L,null,null));
scheduledServiceIml.addTask(new ScheduledTaskTot("T0003","demo.knowledgepoints.scheduledtask.iml.TaskServcesIml","Test3",1000L,5000L,null,null));
} catch (Exception e) {
e.printStackTrace();
}
}
}

输出结果:

参考资料:https://blog.csdn.net/money9sun/article/details/88575704?tdsourcetag=s_pctim_aiomsg

如有疑问请留言,每一个都会及时回复。


《Java知识应用》Java-线程池(ScheduledExecutorService)的更多相关文章

  1. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  2. Java多线程-新特性-线程池

    Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...

  3. 深入理解Java自带的线程池和缓冲队列

    前言 线程池是什么 线程池的概念是初始化线程池时在池中创建空闲的线程,一但有工作任务,可直接使用线程池中的线程进行执行工作任务,任务执行完成后又返回线程池中成为空闲线程.使用线程池可以减少线程的创建和 ...

  4. Java:多线程,线程池,用Executors静态工厂生成常用线程池

    一: newSingleThreadExecutor 创建一个单线程的线程池,以无界队列方式运行.这个线程池只有一个线程在工作(如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它.)此线程池 ...

  5. 【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法

    jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口  |–Execut ...

  6. java高并发之线程池

    Java高并发之线程池详解   线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...

  7. Java并发编程:线程池ThreadPoolExecutor

    多线程的程序的确能发挥多核处理器的性能.虽然与进程相比,线程轻量化了很多,但是其创建和关闭同样需要花费时间.而且线程多了以后,也会抢占内存资源.如果不对线程加以管理的话,是一个非常大的隐患.而线程池的 ...

  8. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  9. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  10. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

随机推荐

  1. c++中实现单例模式singleton class

    本文首发于个人博客https://kezunlin.me/post/8932eaec/,欢迎阅读! singleton class and usage in c++. Guide what singl ...

  2. 【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程

    概述 本文以SpringBoot应用为基础,尝试分析基于注解@Configuration的配置类是如何向Spring容器注册BeanDefinition的过程 其中主要分析了 Configuratio ...

  3. IO流之ZipInputStream和ZipOutputStream的认识及使用

    转载https://blog.csdn.net/weixin_39723544/article/details/80611810 工具类 import java.io.*;import java.ut ...

  4. linux [CTRL]+c与[CTRL]+d

    [CTRL]+c:中断目前程序.用于在linux中输入了错误的命令或者参数,有的时候会在系统不停的运行,如果想让程序需停下来,可以使用[CTRL]+C [CTRL]+d:这个组合键代表着键盘输入结束( ...

  5. 创建指定python版本的虚拟环境

    使用virtualenvwrapper管理虚拟环境 鉴于virtualenv不便于对虚拟环境集中管理,所以推荐直接使用virtualenvwrapper. virtualenvwrapper提供了一系 ...

  6. django框架简介及自定义简易版框架

    web应用与web框架本质 概念 什么是web应用程序呢? Web应用程序就一种可以通过互联网来访问资源的应用程序, 用户可以只需要用一个浏览器而不需要安装其他程序就可以访问自己需要的资源. 应用软件 ...

  7. for源码实现

    for源码实现 我们知道,java的while和for基本上是实现一样的功能,这样会不会有一点缺点,同时java的迭代器显得尤为的麻烦. python的for和while就不同了,在实现迭代的功能的情 ...

  8. C语言I作业11

    C语言 博客作业11 问题 回答 C语言程序设计II 博客作业11 这个作业要求在哪里 作业要求 我在这个课程的目标是 理解和弄懂局部变量和全局变量,静态变量和动态变量 这个作业在哪个具体方面帮助我实 ...

  9. 机器学习十大算法总览(含Python3.X和R语言代码)

    引言 一监督学习 二无监督学习 三强化学习 四通用机器学习算法列表 线性回归Linear Regression 逻辑回归Logistic Regression 决策树Decision Tree 支持向 ...

  10. NSSearchPathForDirectoriesInDomains用法

    iPhone会为每一个应用程序生成一个私有目录,这个目录位于: /Users/sundfsun2009/Library/Application Support/iPhone Simulator/Use ...