《Java知识应用》Java-线程池(ScheduledExecutorService)
先回顾一下,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)的更多相关文章
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- 深入理解Java自带的线程池和缓冲队列
前言 线程池是什么 线程池的概念是初始化线程池时在池中创建空闲的线程,一但有工作任务,可直接使用线程池中的线程进行执行工作任务,任务执行完成后又返回线程池中成为空闲线程.使用线程池可以减少线程的创建和 ...
- Java:多线程,线程池,用Executors静态工厂生成常用线程池
一: newSingleThreadExecutor 创建一个单线程的线程池,以无界队列方式运行.这个线程池只有一个线程在工作(如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它.)此线程池 ...
- 【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法
jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口 |–Execut ...
- java高并发之线程池
Java高并发之线程池详解 线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...
- Java并发编程:线程池ThreadPoolExecutor
多线程的程序的确能发挥多核处理器的性能.虽然与进程相比,线程轻量化了很多,但是其创建和关闭同样需要花费时间.而且线程多了以后,也会抢占内存资源.如果不对线程加以管理的话,是一个非常大的隐患.而线程池的 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
随机推荐
- windows 10 上使用pybind11进行C++和Python代码相互调用 | Interfacing C++ and Python with pybind11 on windows 10
本文首发于个人博客https://kezunlin.me/post/8b9c051d/,欢迎阅读! Interfacing C++ and Python with pybind11 on window ...
- 全栈项目|小书架|微信小程序-登录及token鉴权
小程序登录 之前也写过微信小程序登录的相关文章: 微信小程序~新版授权用户登录例子 微信小程序-携带Token无感知登录的网络请求方案 微信小程序开通云开发并利用云函数获取Openid 也可以通过官方 ...
- mr的partition分区
1.Partitioner 组件通过让 Map 对 Key 进行分区,从而将不同分区的 Key 交由不同的 Reduce 处理.Partition属于map端 2.分区的总数与任务的reduce任务数 ...
- Winows下安装RabbitMQ
RabbitMQ的简介 RabbitMQ是一套开源(MPL)的消息队列服务软件,是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源 ...
- 程序员的算法课(19)-常用的图算法:最短路径(Shortest Path)
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...
- 程序员的算法课(11)-KMP算法
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...
- element table 先显示暂无数据 之后再加载数据 问题
项目中的表格请求数据时,进去页面,先出现 ''暂无数据'' 字样闪现一下之后在进行加载数据,用户体验十分不好 解决办法: <template> <el-table :data=&qu ...
- 比特宇宙-TCP/IP的诞生
前情回顾: 我是一个explorer的线程 我是一个杀毒软件线程 我是一个IE浏览器线程 比特宇宙创世不久,宇宙中开始出现文明. 文明不断碰撞.融合.进化,逐渐分化为几大派系: 施行Unix体制的帝国 ...
- PHP命令空间namespace及use的用法
使用namespace的目的 命名空间将代码划分出不同的空间(区域),每个空间的常量.函数.类(为了偷懒,我下边都将它们称为元素)的名字互不影响, 这个有点类似我们常常提到的'封装'的概念. 团队合作 ...
- GO富集分析示例【华为云技术分享】
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...