先回顾一下,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. Android DecorView 与 Activity 绑定原理分析

    一年多以前,曾经以为自己对 View 的绘制已经有了解了,事后发现也只是懂了些皮毛而已.经过一年多的实战,Android 和 Java 基础都有了提升,时机成熟了,是时候该去总结 View 的绘制流程 ...

  2. LMS自适应天线阵列设计 MATLAB

    在自适应天线课上刚刚学了LMS自适应阵,先出一个抢先版贴一下结果,抢先某个小朋友一步. 关于LMS的具体介绍,直接看wiki里的吧,解释的比书上简明:传送门:https://en.wikipedia. ...

  3. 微信中使用popup等弹窗组件时点击输入框input键盘弹起导致IOS中按钮无效处理办法

    因为在IOS微信中在弹窗中使用input使键盘弹起,使弹窗的位置上移,当键盘关闭时页面还在上面,弹窗位移量也在上面,只有下拉才能回到原位,这样弹窗也消失了.我的处理办法就是在键盘弹起和消失的时候,让页 ...

  4. linux 正确的关机流程

    查看系统的使用状态 1.使用who命令查看在线用户. 2.使用netstat -a或ss -tnl查看网络状态: 3.使用ps -aux 查看后台运行的程序. 通过上述操作可以了解系统目前使用状态,从 ...

  5. Java正则表达式Pattern和Matcher类

    转载自--小鱼儿是坏蛋(原文链接) 概述 Pattern类的作用在于编译正则表达式后创建一个匹配模式.    Matcher类使用Pattern实例提供的模式信息对正则表达式进行匹配 Pattern类 ...

  6. 我的 Input框 不可能这么可爱

    <input /> 标签是我们日常开发中非常常见的替换元素了,但是最近在刷 whattwg 跟 MDN 的时候发现 跟 <input /> 有很多相关的属性,选择器都没怎么用过 ...

  7. 【RN - 基础】之FlexBox弹性布局

    前言 弹性盒模型(The Flexible Box Module),又叫FlexBox,意为“弹性布局”,旨在通过弹性的方式来对齐和分布容器中内容的空间,使其能适应不同的屏幕,为盒装模型提供最大的灵活 ...

  8. CentOS 7 Nginx部署.NET Core Web应用

    部署.NET Core运行时 必要前提 在安装.NET Core前,需要注册Microsoft签名秘钥并添加Microsoft产品提要,每台机器只需要注册一次,执行如下命令: sudo rpm -Uv ...

  9. ios中数据存储方式

    以上三种不能存储大批量数据 plist只能先取出来 里面的数据 覆盖存储 SQLLite3 数据库 纯C语言 轻量级 CoreData  基于SQLLite3 OC版本 重量级 大批量数据缓存 SQL ...

  10. linux搭建Git

    安装依赖库和编译工具为了后续安装能正常进行,我们先来安装一些相关依赖库和编译工具yum install curl-devel expat-devel gettext-devel openssl-dev ...