ScheduledExecutorServiceAPI计划任务使用

    科技2022-08-06  98

    使用callable进行延迟运行

    public class MyCallableA implements Callable<String> { @Override public String call() throws Exception { String name = Thread.currentThread().getName(); System.out.println(name+" callA start "+ System.currentTimeMillis()); TimeUnit.SECONDS.sleep(1); System.out.println(name+" callA end "+ System.currentTimeMillis()); return "result callA"; } } public class MyCallableB implements Callable<String> { @Override public String call() throws Exception { String name = Thread.currentThread().getName(); System.out.println(name+" callB start "+ System.currentTimeMillis()); System.out.println(name+" callB end "+ System.currentTimeMillis()); return "result callB"; } } public static void main(String[] args) { List<Callable> list = new ArrayList<Callable>(); list.add(new MyCallableA()); list.add(new MyCallableB()); // 创建单一任务执行计划 // ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); // 创建多任务执行计划 ScheduledExecutorService ex = Executors.newScheduledThreadPool(2); ScheduledFuture<String> fua = ex.schedule(list.get(0), 4, TimeUnit.SECONDS); ScheduledFuture<String> fub = ex.schedule(list.get(1), 4, TimeUnit.SECONDS); System.out.println("main x start "+System.currentTimeMillis()); try { System.out.println("返回值A "+fua.get()); System.out.println("返回值B "+fub.get()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("main x end "+System.currentTimeMillis()); } }

    单一任务执行计划 测试结果 main x start 1601866894411 pool-1-thread-1 callA start 1601866898413 pool-1-thread-1 callA end 1601866899414 返回值A result callA pool-1-thread-1 callB start 1601866899414 pool-1-thread-1 callB end 1601866899414 返回值B result callB main x end 1601866899415 总的运行时间是延迟时间加上两个任务的运行时间,第二个人任务是在第一个任务执行完后再执行。

    创建多任务执行计划 测试结果 main x start 1601866979774 pool-1-thread-1 callA start 1601866983775 pool-1-thread-2 callB start 1601866983775 pool-1-thread-2 callB end 1601866983775 pool-1-thread-1 callA end 1601866984775 返回值A result callA 返回值B result callB main x end 1601866984775 到达延迟执行时间后两个任务同时运行。

    scheduleAtFixedRate 实现周期性执行 scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); command 自定义的runnable接口 initialDelay 延迟执行时间 period 周期 unit 时间单位

    public class MyRunnableA implements Runnable { @Override public void run() { String name = Thread.currentThread().getName(); System.out.println(name+" callA start "+ System.currentTimeMillis()); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(name+" callA end "+ System.currentTimeMillis()); } } public static void main(String[] args) { ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); System.out.println("main x start "+System.currentTimeMillis()); ex.scheduleAtFixedRate(new MyRunnableA(), 5, 5, TimeUnit.SECONDS); System.out.println("main x END "+System.currentTimeMillis()); }

    运行时间大于周期时间(period ) 测试结果 main x start 1601867868366 main x END 1601867868369 pool-1-thread-1 callA start 1601867873370 pool-1-thread-1 callA end 1601867875371 pool-1-thread-1 callA start 1601867875372 pool-1-thread-1 callA end 1601867877375 pool-1-thread-1 callA start 1601867877377 延迟5秒后每两秒执行一次,而不是设定的1秒一次。

    运行时间小于周期时间(period ) 测试结果 main x start 1601867934619 main x END 1601867934621 pool-1-thread-1 callA start 1601867939625 pool-1-thread-1 callA end 1601867941626 pool-1-thread-1 callA start 1601867944622 pool-1-thread-1 callA end 1601867946623 延迟5秒后每5秒执行一次,任务执行完后会等待到5秒后再开启下次任务的周期性执行。

    scheduleWithFixedDelay 实现周期性运行 scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); command 自定义的runnable接口 initialDelay 延迟执行时间 period 周期 unit 时间单位 设置多任务之间的固定间隔运行,不会存在超时与非超时情况, ex.scheduleWithFixedDelay(new MyRunnableA(), 2, 3, TimeUnit.SECONDS); 表示延迟2秒运行,在任务A执行完毕后再间隔3秒开启下一周期任务执行。

    getQueue()和 remove(Object x)方法 getQueue() 获取到队列中的任务,这些任务是将要运行的,正在运行的不在其中。 remove() 删除队列中的任务,正在运行中的任务无法删除,已运行完的任务是可以从队列中删除的。

    public class MyRunnableB implements Runnable { private String name; public MyRunnableB(String name) { super(); this.name = name; } @Override public void run() { System.out.println(name+" callA start "+ System.currentTimeMillis()); } } public static void main(String[] args) { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(2); Runnable a = new MyRunnableB("A"); Runnable b = new MyRunnableB("B"); Runnable c = new MyRunnableB("C"); ScheduledFuture aa= pool.scheduleAtFixedRate(a, 3, 1, TimeUnit.SECONDS); ScheduledFuture bb=pool.scheduleAtFixedRate(b, 5, 1, TimeUnit.SECONDS); ScheduledFuture cc=pool.scheduleAtFixedRate(c, 10, 1, TimeUnit.SECONDS); System.out.println("***"); try { //删除成功 //TimeUnit.SECONDS.sleep(4); TimeUnit.SECONDS.sleep(6); System.out.println("删除任务B " + pool.remove((Runnable)bb)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } BlockingQueue<Runnable> queue = pool.getQueue(); Iterator<Runnable> it = queue.iterator(); while (it.hasNext()) { Runnable h = it.next(); System.out.println("队列中的 " + h); } }

    B任务删除成功 A callA start 1601870104613 B callA start 1601870104613 A callA start 1601870105612 删除任务B true 队列中的 java.util.concurrent.ScheduledThreadPoolExecutor S c h e d u l e d F u t u r e T a s k @ 5 c 647 e 05 队 列 中 的 j a v a . u t i l . c o n c u r r e n t . S c h e d u l e d T h r e a d P o o l E x e c u t o r ScheduledFutureTask@5c647e05 队列中的 java.util.concurrent.ScheduledThreadPoolExecutor ScheduledFutureTask@5c647e05java.util.concurrent.ScheduledThreadPoolExecutorScheduledFutureTask@33909752 A callA start 1601870108612 A callA start 1601870109613 C callA start 1601870109613 A callA start 1601870110612 C callA start 1601870110614

    setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) 停掉任务 当ScheduledThreadPoolExecutor执行了shutdown()方法时,任务是否继续进行,默认是true继续执行,当传入false时就不会继续执行。不能与scheduleWithFixedDelay与scheduleAtFixedRate方法进行联用(不起作用,都会停掉任务)。

    public static void main(String[] args) { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1); Runnable a = new MyRunnableB("A"); pool.schedule(a, 3, TimeUnit.SECONDS); pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); pool.shutdown(); System.out.println("任务已经停掉"); }

    测试结果 任务已经停掉

    去掉pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false)后测试结果 任务已经停掉 A callA start 1601870864312

    setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value)方法停掉周期性任务 当使用scheduleAtFixedRate和scheduleWithFixedDelay方法时,如果调用ScheduledThreadPoolExecutor执行了shutdown()方法,任务是否继续进行,true继续执行,当传入false时就不会继续执行。 ’

    public static void main(String[] args) { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1); Runnable a = new MyRunnableB("A"); pool.scheduleAtFixedRate(a, 5, 5, TimeUnit.SECONDS); //继续执行 // pool.setContinueExistingPeriodicTasksAfterShutdownPolicy(true); pool.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); pool.shutdown(); System.out.println("任务已经停掉"); }

    不继续执行 任务已经停掉

    继续执行 任务已经停掉 A callA start 1601871152082 A callA start 1601871157082 A callA start 1601871162083

    cancel(boolean value)与setRemoveOnCancelPolicy(boolean value) cancel(boolean value) 方法是否取消任务,取消任务也不删除队列中的任务(任务不执行),正在运作中的任务可以结合if(Thread.currentThread().isInterrupted()==true)中断任务。 setRemoveOnCancelPolicy(boolean value) 方法取消任务后是否将任务从队列中删除。

    取消任务,不删除队列中的任务

    public static void main(String[] args) { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1); Runnable a = new MyRunnableB("A"); ScheduledFuture fua = pool.schedule(a, 0, TimeUnit.SECONDS); System.out.println(fua.cancel(true)); BlockingQueue<Runnable> queue = pool.getQueue(); Iterator<Runnable> it = queue.iterator(); while (it.hasNext()) { Runnable h = it.next(); System.out.println("队列中的 " + h); } System.out.println("main end"); }

    测试结果 true 队列中的 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@70dea4e

    中断执行中的任务

    public class MyRunnableC implements Runnable { private String name; public MyRunnableC(String name) { super(); this.name = name; } @Override public void run() { try { while(true) { if(Thread.currentThread().isInterrupted()==true) { throw new InterruptedException(); } System.out.println(name+" run start "+ System.currentTimeMillis()); TimeUnit.SECONDS.sleep(1); } } catch (InterruptedException e) { e.printStackTrace(); System.out.println("线程中断了"); } } } ** public static void main(String[] args) { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1); Runnable a = new MyRunnableC("A"); ScheduledFuture fua = pool.schedule(a, 0, TimeUnit.SECONDS); BlockingQueue<Runnable> queue = pool.getQueue(); System.out.println("queue size "+queue.size()); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(fua.cancel(true)); queue = pool.getQueue(); System.out.println("queue size "+queue.size()); System.out.println("main end"); }

    测试结果 A run start 1601872391249 queue size 0 A run start 1601872392251 true queue size 0 main end java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Unknown Source) at java.util.concurrent.TimeUnit.sleep(Unknown Source) at scheduledExecutorService.MyRunnableC.run(MyRunnableC.java:22) at java.util.concurrent.Executors R u n n a b l e A d a p t e r . c a l l ( U n k n o w n S o u r c e ) a t j a v a . u t i l . c o n c u r r e n t . F u t u r e T a s k . r u n ( U n k n o w n S o u r c e ) a t j a v a . u t i l . c o n c u r r e n t . S c h e d u l e d T h r e a d P o o l E x e c u t o r RunnableAdapter.call(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor RunnableAdapter.call(UnknownSource)atjava.util.concurrent.FutureTask.run(UnknownSource)atjava.util.concurrent.ScheduledThreadPoolExecutorScheduledFutureTask.access 201 ( U n k n o w n S o u r c e ) a t j a v a . u t i l . c o n c u r r e n t . S c h e d u l e d T h r e a d P o o l E x e c u t o r 201(Unknown Source) at java.util.concurrent.ScheduledThreadPoolExecutor 201(UnknownSource)atjava.util.concurrent.ScheduledThreadPoolExecutorScheduledFutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 线程中断了

    取消任务并且删除队列中的任务

    public static void main(String[] args) { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1); Runnable a = new MyRunnableC("A"); ScheduledFuture fua = pool.schedule(a, 1, TimeUnit.SECONDS); pool.setRemoveOnCancelPolicy(true); System.out.println(fua.cancel(true)); BlockingQueue<Runnable> queue = pool.getQueue(); Iterator<Runnable> it = queue.iterator(); while (it.hasNext()) { Runnable h = it.next(); System.out.println("队列中的 " + h); } System.out.println("main end"); }

    测试结果 true main end

    Processed: 0.012, SQL: 8