赞
踩
说明:本文对线程池的四种使用方式分别进行了实现,每种方式的详细介绍及关键点在代码的备注中
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.concurrent.*;
-
- public class Main {
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- //线程池的四种使用方式(说明及关键点在实现方法中):
- //方式一:
- newCachedThreadPool();
- //方式二:
- // fixdThreadPool(5);
- //方式三:
- // newScheduledThreadPool(6);
- //方式四
- // newSingleThreadExecutor();
- }
-
- //方式一:newCachedThreadPool
- // 可缓存的线程池,该线程池中“没有核心线程,非核心线程的数量为无限大”,(核心线程在没用时候也不回收)
- // 就是说当有需要时创建线程来执行任务,没有需要时“回收”线程,适用于耗时少,任务量大的情况。
- //注意:线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
- // 加上//****处那段代码就是体现此特点
- private static void newCachedThreadPool() throws ExecutionException, InterruptedException {
- ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
- for (int i = 0; i < 20; i++) {//线程池中线程数可以有无限大个
- // //**** 线程先睡一秒,再执行。由于睡一秒的过程前面线程已经执行完毕,所以不用开启新的线程,直接复用前面线程即可。
- // 所以才会重复用第一个线程
- // final int index = i;
- // try {
- // Thread.sleep(index * 1000);
- // }
- // catch (InterruptedException e) {
- // e.printStackTrace();
- // }
- //执行线程的方法1:调用runnableh中的run方法,此方法不向客户端返回执行结果
- cachedThreadPool.execute(new Runnable() {
- @Override
- public void run() {
- System.out.println("执行线程:" + Thread.currentThread().getName());
- }
- });
- }
- }
-
- //方式二:fixdThreadPool
- // 定长的线程池,“有核心线程,核心线程的即为最大的线程数量,没有非核心线程”
- // 创建一个定长线程池,超出的线程会在队列中等待,即使线程空闲也不会回收。
- //注意:1.此处线程池传入创建的线程有5个,但是有十个任务等待执行,先FIFO的顺序执行前五个线程,后五个在队列中等待。
- // 前五个线程执行完毕后再按照FIFO的顺序执行。
- // 2.定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。
- private static void fixdThreadPool(int size) throws ExecutionException, InterruptedException {
- ExecutorService executorService = Executors.newFixedThreadPool(size);
- for (int i = 0; i < 10; i++) {
- //3.此处算法在线程执行直线进行睡眠,但是不会像newCatchThreadPool中那样重复在执行线程1,
- // 因为这里线程直接是创建了固定大小的,直接用(不用也不会回收)
- final int index = i;
- try {
- Thread.sleep(index * 1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- //执行线程的方法2:调用Callable中的call方法,此方法可以向客户端返回执行结果
- Future<Integer> task = executorService.submit(new Callable<Integer>() {
- @Override
- public Integer call() throws Exception {
- System.out.println("执行线程:" + Thread.currentThread().getName());
- return null;
- }
- });
- System.out.println("第" + i + "次计算,结果:" + task.get());
- }
- }
-
- //方式三:newScheduledThreadPool,创建一个定长的线程池,支持定时及周期性任务执行
- private static void newScheduledThreadPool(int size) {
- ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(size);
- Date d = new Date();
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- System.out.println(df.format(d));
- //法一:schedule()延迟一定时间后执行任务
- //参数1:为执行的任务;参数2:任务的延迟间隔;参数3:为延迟执行的时间单位:
- scheduledExecutorService.schedule(new Runnable() {
- @Override
- public void run() {
- Date d = new Date();
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- System.out.println(df.format(d));
- System.out.println("执行线程:" + Thread.currentThread().getName());
- }
- }, 10, TimeUnit.SECONDS); //表示线程延迟十秒执行,任务只执行一次
-
- //法二:scheduleAtFixedRate(...):按指定频率周期执行某个任务。如12:00执行第一次,15:00执行第二次,18:00执行第三次...
- //(个人认为与法三的区别是:每个任务的开始时间是以一定周期开始的,后面任务开始时可能前面任务还未完成。
- // 而法三则是在前面任务完成的时间点上延迟一定时间执行)
- // 参数1:为执行的任务;参数2:初始任务延迟时间;参数3:执行的周期;参数4:为延迟执行的时间单位:
- // scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- // @Override
- // public void run() {
- // Date d = new Date();
- // SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- // System.out.println(df.format(d));
- // System.out.println("执行线程:"+Thread.currentThread().getName());
- // }
- // },2,3,TimeUnit.SECONDS);//初始化延迟2s开始执行,每隔3s重新执行一次任务。
- //上面如果当前时间是10点,设置initialDelay:2,period:3,unit:小时
- //第一次:10:00 + 2 = 12:00
- //第二次:10:00 + 2 + 3 =15:00
- //第三次:10:00 + 2 + 2*3 =18:00
- //第n次:10:00 + 2 + n*3...
-
- //法三:scheduleWithFixedDelay(...):按指定频率间隔执行某个任务
- // 参数1:为执行的任务;参数2:为初始延迟时间;参数3:后续任务的延迟执行时间;参数4:为延迟执行的时间单位:
- // 解释:
- // 第一次调度开始时间点=当前时间+initialDelay
- // 下一次调度开始时间点=上一次task完成时间点+delay
- // scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
- // @Override
- // public void run() {
- // Date d = new Date();
- // SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- // System.out.println(df.format(d));
- // System.out.println("执行线程:"+Thread.currentThread().getName());
- // }
- // },5,3,TimeUnit.SECONDS);//初始化延迟5s开始执行,后续任务开始时间是在其前一个任务结束后延迟2s重新执行。
- }
-
- //方式四:newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,
- // 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
- private static void newSingleThreadExecutor() {
- ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
- for (int i = 0; i < 10; i++) {
- final int index=i;
- singleThreadExecutor.execute(new Runnable() {
- @Override
- public void run() {
- try {
- System.out.println("任务:"+index);
- System.out.println("执行线程:"+Thread.currentThread().getName());
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- });
- }
- }
- }
-

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。