类ScheduledExecutorService的主要作用就是可以将定时任务与线程池功能结合使用。实现类ScheduledThreadPoolExecutor的父接口还是Executor,父类是ThreadPoolExecutor,其部分方法是父类ThreadPoolExecutor提供并在子类ScheduledThreadPoolExecutor中重写的,比如submit()重载方法或shutdown()等方法。
使用Callable接口进行任务延迟运行的实验,具有返回值的功能。
package mycallable;
import java.util.concurrent.Callable;
public class MyCallableA implements Callable {
@Override
public String call() throws Exception {
try {
System.out.println("callA begin " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("callA end " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
return "returnA";
}
}
package mycallable;
import java.util.concurrent.Callable;
public class MyCallableB implements Callable {
@Override
public String call() throws Exception {
System.out.println("callB begin " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
System.out.println("callB end " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
return "returnB";
}
}
package test.run;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import mycallable.MyCallableA;
import mycallable.MyCallableB;
public class Run1 {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
try {
List callableList = new ArrayList();
callableList.add(new MyCallableA());
callableList.add(new MyCallableB());
// 调用方法newSingleThreadScheduledExecutor
// 取得一个单任务的计划任务执行池
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture futureA = executor.schedule(callableList.get(0), 4L, TimeUnit.SECONDS);
ScheduledFuture futureB = executor.schedule(callableList.get(1), 4L, TimeUnit.SECONDS);
System.out.println(" X=" + System.currentTimeMillis());
System.out.println("返回值A:" + futureA.get());
System.out.println("返回值B:" + futureB.get());
System.out.println(" Y=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
package test.run;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import mycallable.MyCallableA;
import mycallable.MyCallableB;
public class Run2 {
public static void main(String[] args) {
try {
List callableList = new ArrayList();
callableList.add(new MyCallableA());
callableList.add(new MyCallableB());
// 调用方法newScheduledThreadPool(corePoolSize >1)
// 取得一个同时运行corePoolSize任务个数的计划任务执行池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
ScheduledFuture futureA = executor.schedule(callableList.get(0), 4L, TimeUnit.SECONDS);
ScheduledFuture futureB = executor.schedule(callableList.get(1), 4L, TimeUnit.SECONDS);
System.out.println(" X=" + System.currentTimeMillis());
System.out.println("返回值A:" + futureA.get());
System.out.println("返回值B:" + futureB.get());
System.out.println(" Y=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
package test.run;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import mycallable.MyCallableA;
import mycallable.MyCallableB;
public class Run3 {
public static void main(String[] args) {
try {
List callableList = new ArrayList();
callableList.add(new MyCallableA());
callableList.add(new MyCallableB());
// 调用方法newScheduledThreadPool(1)
// 取得一个单任务的计划任务执行池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
ScheduledFuture futureA = executor.schedule(callableList.get(0), 4L, TimeUnit.SECONDS);
ScheduledFuture futureB = executor.schedule(callableList.get(1), 4L, TimeUnit.SECONDS);
System.out.println(" X=" + System.currentTimeMillis());
System.out.println("返回值A:" + futureA.get());
System.out.println("返回值B:" + futureB.get());
System.out.println(" Y=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
(单任务调度)从X到Y的运行时间为7秒,阻塞点是get()方法。public
使用Runnable接口进行无返回值的计划任务实例
package mycallable;
public class MyRunnableA implements Runnable {
@Override
public void run() {
try {
System.out
.println("runnableA begin " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
Thread.sleep(3000);
System.out
.println("runnableA end " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
package mycallable;
public class MyRunnableB implements Runnable {
@Override
public void run() {
System.out.println("runnableB begin " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
System.out.println("runnableB end " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
}
}
package test.run;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnableA;
import mycallable.MyRunnableB;
public class Run {
public static void main(String[] args) {
List runnableList = new ArrayList();
runnableList.add(new MyRunnableA());
runnableList.add(new MyRunnableB());
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
System.out.println(" X=" + System.currentTimeMillis());
executor.schedule(runnableList.get(0), 0L, TimeUnit.SECONDS);
executor.schedule(runnableList.get(1), 0L, TimeUnit.SECONDS);
System.out.println(" Y=" + System.currentTimeMillis());
}
}
package mycallable;
import java.util.concurrent.Callable;
public class MyCallableA implements Callable {
public String call() throws Exception {
System.out.println("a call run =" + System.currentTimeMillis());
return "returnA";
}
}
package test.run;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import mycallable.MyCallableA;
public class Run {
public static void main(String[] args) {
try {
List callableList = new ArrayList();
callableList.add(new MyCallableA());
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
System.out.println("X=" + System.currentTimeMillis());
ScheduledFuture futureA = executor.schedule(callableList.get(0), 4L, TimeUnit.SECONDS);
System.out.println(futureA.get() + " A=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
5.1 接口scheduleAtFixedRate原型定义及参数说明
command:执行线程
initialDelay:初始化延时
period:两次开始执行最小间隔时间
unit:计时单位
package mycallable;
public class MyRunnable implements Runnable {
@Override
public void run() {
try {
System.out.println(
" begin =" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName());
Thread.sleep(4000);
System.out.println(
" end =" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package test.run;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
public class Run {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
System.out.println(" X=" + System.currentTimeMillis());
executor.scheduleAtFixedRate(new MyRunnable(), 1, 2, TimeUnit.SECONDS);
System.out.println(" Y=" + System.currentTimeMillis());
}
}
scheduleAtFixedRate()方法返回的ScheduledFuture对象无法获得返回值,也就是scheduleAtFixedRate()方法不具有获得返回值的功能,而schedule()方法却可以获得返回值。所以当使用scheduleAtFixedRate()方法实现重复运行任务的效果时,需要结合自定义的Runnable接口的实现类,不要使用FutureTask类,因为FutureTask类并不能实现重复运行的效果。
command:执行线程
initialDelay:初始化延时
period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
unit:计时单位
package mycallable;
public class MyRunnable implements Runnable {
@Override
public void run() {
try {
System.out.println(
" begin =" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName());
Thread.sleep(4000);
System.out.println(
" end =" + System.currentTimeMillis() + " ThreadName=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package test.run;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
public class Run {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
System.out.println(" X=" + System.currentTimeMillis());
executor.scheduleWithFixedDelay(new MyRunnable(), 1, 2, TimeUnit.SECONDS);
System.out.println(" Y=" + System.currentTimeMillis());
}
}
方法getQueue()的作用是取得队列中的任务,而这些任务是未来将要运行的,正在运行的任务不在此队列中。使用scheduleAtFixedRate()和scheduleWithFixedDelay()两个方法实现周期性执行任务时,未来欲执行的任务都是放入此队列中。
package mycallable;
public class MyRunnable implements Runnable {
private String username;
public MyRunnable(String username) {
super();
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
System.out.println("run! username=" + username + " " + Thread.currentThread().getName());
}
}
package test.run;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
public class Run1 {
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
Runnable runnable1 = new MyRunnable("A");
Runnable runnable2 = new MyRunnable("B");
Runnable runnable3 = new MyRunnable("C");
Runnable runnable4 = new MyRunnable("D");
Runnable runnable5 = new MyRunnable("E");
System.out.println(runnable1.hashCode());
System.out.println(runnable2.hashCode());
System.out.println(runnable3.hashCode());
System.out.println(runnable4.hashCode());
System.out.println(runnable5.hashCode());
executor.scheduleAtFixedRate(runnable1, 10, 2, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(runnable2, 10, 2, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(runnable3, 10, 2, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(runnable4, 10, 2, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(runnable5, 10, 2, TimeUnit.SECONDS);
System.out.println("");
BlockingQueue queue = executor.getQueue();
Iterator iterator = queue.iterator();
while (iterator.hasNext()) {
Runnable runnable = (Runnable) iterator.next();
System.out.println("队列中的:" + runnable);
}
}
}
package test.run;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
public class Run2 {
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
Runnable runnable1 = new MyRunnable("A");
Runnable runnable2 = new MyRunnable("B");
ScheduledFuture future1 = executor.scheduleAtFixedRate(runnable1, 0, 2, TimeUnit.SECONDS);
Thread.sleep(1000);
ScheduledFuture future2 = executor.scheduleAtFixedRate(runnable2, 10, 2, TimeUnit.SECONDS);
Thread.sleep(5000);
System.out.println(executor.remove((Runnable) future2));
System.out.println("");
BlockingQueue queue = executor.getQueue();
Iterator iterator = queue.iterator();
while (iterator.hasNext()) {
Runnable runnable = (Runnable) iterator.next();
System.out.println("队列中的:" + runnable);
}
}
}
方法setExecuteExistingDelayedTasksAfterShutdownPolicy()的作用是当对ScheduledThreadPoolExecutor执行了shutdown()方法时,任务是否继续执行,默认值是true,也就是当调用了shutdown()方法时任务还是继续运行,当使用setExecuteExistingDelayedTasksAfterShutdownPolicy(false)时任务不再运行。
package mycallable;
public class MyRunnable implements Runnable {
private String username;
public MyRunnable(String username) {
super();
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
System.out.println("run! username=" + username + " " + Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
}
}
package test.run;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
/**
* 虽然shutdown()但任务还是执行了
* @author linhaiy
*
*/
public class Run1 {
public static void main(String[] args) throws InterruptedException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
Runnable runnable1 = new MyRunnable("A");
Runnable runnable2 = new MyRunnable("B");
executor.schedule(runnable1, 3, TimeUnit.SECONDS);
executor.shutdown();
System.out.println("已经shutdown了");
}
}
package test.run;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
/**
* 任务被取消执行,进程销毁了
* @author linhaiy
*
*/
public class Run2 {
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
Runnable runnable1 = new MyRunnable("A");
Runnable runnable2 = new MyRunnable("B");
executor.schedule(runnable1, 3, TimeUnit.SECONDS);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
executor.shutdown();
System.out.println("已经shutdown了");
}
}
方法setExecuteExistingDelayedTasksAfterShutdownPolicy()可以与schedule()和shutdown()方法联合使用,但setExecuteExistingDelayedTasksAfterShutdownPolicy()方法不能与scheduleAtFixedRate()和scheduleWithFixedDelay()方法联合使用。那么如果想实现shutdown关闭线程池后,池中的任务还会继续重复运行, 则要将scheduleAtFixedRate()和scheduleWithFixedDelay()方法与setExecuteExistingDelayedTasksAfterShutdownPolicy()方法联合使用。
方法setContinueExistingPeriodicTasksAfterShutdownPolicy()传入true的作用是当使用scheduleAtFixedRate()方法或scheduleWithFixedDelay()方法时,如果调用ScheduledThreadPoolExecutor对象的shutdown()方法,任务还会继续运行,传入false时任务不运行,进程销毁。如果使用scheduleAtFixedRate()结合shutdown()方法想实现任务继续运行的效果,则必须使用setContinueExistingPeriodicTasksAfterShutdownPolicy(true)代码。
package mycallable;
public class MyRunnable implements Runnable {
private String username;
public MyRunnable(String username) {
super();
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
System.out.println("run! username=" + username + " " + Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
}
}
package test.run;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
public class Run1 {
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
Runnable runnable1 = new MyRunnable("A");
executor.scheduleAtFixedRate(runnable1, 1, 2, TimeUnit.SECONDS);
executor.shutdown();
System.out.println("执行了shutdown!");
}
}
package test.run;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import mycallable.MyRunnable;
public class Run2 {
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
Runnable runnable1 = new MyRunnable("A");
executor.scheduleAtFixedRate(runnable1, 1, 2, TimeUnit.SECONDS);
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
executor.shutdown();
System.out.println("执行了shutdown!");
}
}
10.1 方法cancel(boolean)的作用设定是否取消任务。
10.2 方法setRemoveOnCancelPolicy(boolean)的作用设定是否将取消后的任务从队列中清除。
10.3 当执行cancel()方法后任务虽然被成功取消,但还是在队列中存在。
10.4 在队列中的任务被成功取消,任务也不再运行。
10.5 正在运行的任务可以停止,但要结合if(Thread.currentThread().isInterrupted() == true)判断。
10.6 使用setRemoveOnCancelPolicy(true)代码结合cancel(true),则队列中的任务被删除