先回顾一下,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
如有疑问请留言,每一个都会及时回复。