先回顧一下,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
如有疑問請留言,每一個都會及時回復。