共计 3599 个字符,预计需要花费 9 分钟才能阅读完成。
在 Java 语言中,有两个线程池能够执行定时工作:ScheduledThreadPool 和 SingleThreadScheduledExecutor,其中 SingleThreadScheduledExecutor 能够看做是 ScheduledThreadPool 的单线程版本,它的用法和 ScheduledThreadPool 是一样的,所以本文重点来看 ScheduledThreadPool 线程池的应用。
ScheduledThreadPool 执行定时工作的办法有以下 3 个:
- 应用 schedule 办法执行定时工作,只执行一次定时工作。
- 应用 scheduleAtFixedRate 办法执行定时工作,执行屡次定时工作。
- 应用 scheduleWithFixedDelay 办法执行定时工作,执行屡次定时工作。
接下来咱们看这 3 个办法的具体应用和区别。
1.schedule
schedule 办法只能执行一次定时工作,它须要传递 3 个参数:
- 第 1 个参数:传递一个工作,Runnable 或 Callable 对象;
- 第 2 个参数:增加定时工作后,再过多久开始执行定时工作;
- 第 3 个参数:工夫单位,配合参数 2 一起应用。
上面咱们创立一个 3 秒当前执行的定时工作:
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {
// 创立 ScheduledThreadPool 线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
System.out.println("schedule 办法增加工作:" + LocalDateTime.now());
threadPool.schedule(new Runnable() {
@Override
public void run() {System.out.println("执行 schedule 办法:" + LocalDateTime.now());
}
}, 3, TimeUnit.SECONDS); // 3s 之后执行
// 以下代码是给业务办法一个工夫对照信息
TimeUnit.SECONDS.sleep(10); // 休眠 10s
System.out.println("以后工夫:" + LocalDateTime.now());
}
}
以上程序的执行后果如下图所示:
从上述后果中能够看出,应用 schedule 办法只能执行一次定时工作。
2.scheduleAtFixedRate
scheduleAtFixedRate 办法能够执行屡次定时工作,此办法须要 4 个参数:
- 第 1 个参数:传递一个工作,Runnable 或 Callable 对象;
- 第 2 个参数:增加定时工作后,再过多久开始执行定时工作;
- 第 3 个参数:定时工作执行的工夫距离;
- 第 4 个参数:工夫单位,配合参数 2 和参数 3 一起应用。
上面咱们创立一个 3 秒后执行的定时工作,每个定时工作执行的工夫距离为 2 秒,实现代码如下:
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {
// 创立 ScheduledThreadPool 线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
System.out.println("scheduleAtFixedRate 办法增加工作:" + LocalDateTime.now());
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {System.out.println("执行 scheduleAtFixedRate 办法:" + LocalDateTime.now());
// 休眠 2s
try {TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {e.printStackTrace();
}
}
},
3L, // 3s 后开始执行定时工作
2L, // 定时工作的执行距离为 2s
TimeUnit.SECONDS); // 形容下面两个参数的工夫单位
}
}
以上程序的执行后果如下图所示:
从上述后果能够看出,当工作增加胜利之后,3s 后开始执行第一个定时工作,之后每隔 2s 执行一次定时工作。
3.scheduleWithFixedDelay
scheduleWithFixedDelay 办法的应用和 scheduleAtFixedRate 相似,但执行成果齐全不同,这个很容易了解如果成果一样就不必创立两个办法了。
scheduleWithFixedDelay 办法是在办法执行实现之后,再隔 N 秒执行下一个定时工作,和 scheduleAtFixedRate 的固定工夫执行不同,scheduleWithFixedDelay 办法的执行受定时工作执行的时长影响 ,比方以下代码:
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample {public static void main(String[] args) throws InterruptedException {
// 创立 ScheduledThreadPool 线程池
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
System.out.println("scheduleWithFixedDelay 办法增加工作:" + LocalDateTime.now());
threadPool.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {System.out.println("执行 scheduleWithFixedDelay 办法:" + LocalDateTime.now());
// 休眠 2s
try {TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {e.printStackTrace();
}
}
},
3L, // 3s 后开始执行定时工作
2L, // 定时工作执行完 2s 之后,再执行下一个定时工作
TimeUnit.SECONDS); // 形容下面两个参数的工夫单位
}
}
以上程序的执行后果如下图所示:
从上述后果能够看出,定时工作在 3s 之后开始执行,当前每隔 4s 执行一次,这 4s 蕴含了,定时工作执行破费的 2s,加上每隔 2s 执行一次的工夫距离,也就是说 scheduleWithFixedDelay 是在工作执行完 N 秒之后,再执行下一次定时工作 。
总结
线程池执行定时工作的实现办法有 3 个:
- 应用 schedule 办法执行定时工作,只执行一次定时工作。
- 应用 scheduleAtFixedRate 办法执行定时工作,执行屡次定时工作,它的执行工夫距离是固定的,不受定时工作执行时长影响(定时工作工夫距离 > 工作执行工夫)。
- 应用 scheduleWithFixedDelay 办法执行定时工作,执行屡次定时工作,它是在定时工作执行完之后,再隔 N 秒开始执行下一次定时工作,它的执行工夫受定时工作执行时长影响。
是非审之于己,毁誉听之于人,得失安之于数。
公众号:Java 面试真题解析
面试合集:https://gitee.com/mydb/interview