线程池支持定时以及周期性执行任务,创建一个corePoolSize为传入参数,最大线程数为整形的最大数的线程池

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
ScheduledThreadPoolExecutor类的构造:
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
              new DelayedWorkQueue());
    }
此线程池keepAliveTime参数为0,缓存对列为DelayedWorkQueue。
jdk1.5之前的版本中更多的是借助Timer类来实现,Timer和ScheduledThreadPoolExecutor的区别

a.Timer单线程运行,一旦任务执行缓慢,下一个任务就会推迟,而如果使用了ScheduledThreadPoolExecutor线程数可以自行控制

b.当Timer中的一个任务抛出异常时,会导致其他所有任务不在执行

c.ScheduledThreadPoolExecutor可执行异步的任务,从而得到执行结果

ScheduledExecutorService接口继承了ExecutorService,在ExecutorService的基础上新增了以下几个方法:

schedule方法:

public ScheduledFuture<?> schedule(Runnable command,
                       long delay, TimeUnit unit);
command:执行的任务 Callable或Runnable接口实现类
delay:延时执行任务的时间

unit:延迟时间单位

示例:


        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        ScheduledFuture<String> scheduledFuture = executorService.schedule(new Callable<String>() {
            public String call() throws Exception {
                return "call";
            }
        }, 10, TimeUnit.SECONDS);
        System.out.println(scheduledFuture.get());
        executorService.shutdown();
延迟10秒后,返回call字符串并输出。

执行任务案例:

package com.thread.testExtendsThread.fourPackage;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.*;

/**
 * @author liuchj
 * @version 1.0
 * @className ScheduleThreadTest
 * @description //TODO
 * @date 2019/5/30
 **/
public class ScheduleThreadTest {
    /**
     * 线程安全的队列
     */
    static Queue<String> queue = new ConcurrentLinkedQueue<String>();

    static {
        //入队列
        for (int i = 0; i < 9; i++) {
            queue.add("task-" + i);
        }
    }
    public static void main(String[] args) throws Exception {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        for (int i = 0; i < queue.size(); i++) {
            ScheduledFuture<String> scheduledFuture = executorService.schedule(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    String value = ThreadPoolTask.queue.poll();
                    if (value != "" && null != value) {
                        System.out.println("时间:" + sdf.format(new Date())+"线程" + Thread.currentThread().getName() + " 执行了task: " + value);
                    }
                    return "call";
                }
            }, 3, TimeUnit.SECONDS);

            System.out.println(scheduledFuture.get());
        }

        executorService.shutdown();
    }
}

执行结果:

时间:2019-05-30 03:53:11线程pool-1-thread-1 执行了task: task-0
call
时间:2019-05-30 03:53:14线程pool-1-thread-1 执行了task: task-1
call
时间:2019-05-30 03:53:17线程pool-1-thread-1 执行了task: task-2
call
时间:2019-05-30 03:53:20线程pool-1-thread-1 执行了task: task-3
call
时间:2019-05-30 03:53:23线程pool-1-thread-1 执行了task: task-4
call
时间:2019-05-30 03:53:26线程pool-1-thread-1 执行了task: task-5
call
时间:2019-05-30 03:53:29线程pool-1-thread-1 执行了task: task-6
call
时间:2019-05-30 03:53:32线程pool-1-thread-1 执行了task: task-7
call
Disconnected from the target VM, address: '127.0.0.1:59247', transport: 'socket'
时间:2019-05-30 03:53:35线程pool-1-thread-1 执行了task: task-8
call

②scheduleAtFixedRate方法:


 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                          long initialDelay,
                          long period,
                          TimeUnit unit);
command:执行的任务 Callable或Runnable接口实现类

initialDelay:第一次执行任务延迟时间

period:连续执行任务之间的周期,从上一个任务开始执行时计算延迟多少开始执行下一个任务,但是还会等上一个任务结束之后。
unit:initialDelay和period时间单位

示例: 注意看输出结果


final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        executorService.scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println("时间:" + sf.format(new Date()) );
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },  2, 3, TimeUnit.SECONDS);
输出结果: 
时间:2014-04-01 23:44:48
时间:2014-04-01 23:44:53
时间:2014-04-01 23:44:58
时间:2014-04-01 23:45:03

执行任务案例:

public class ScheduledThreadTest {
    /**
     * 线程安全的队列
     */
    static Queue<String> queue = new ConcurrentLinkedQueue<String>();

    static {
        //入队列
        for (int i = 0; i < 9; i++) {
            queue.add("task-" + i);
        }
    }

    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        System.out.println("时间:" + sdf.format(new Date()) );
        for (int i = 0; i < queue.size(); i++) {
            executor.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {

                    String value = ThreadPoolTask.queue.poll();
                    if (value != "" && null != value) {
                        System.out.println("时间:" + sdf.format(new Date())+" 线程" + Thread.currentThread().getName() + " 执行了task: " + value);
                    }
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },  2, 6, TimeUnit.SECONDS);

        }
//不注释这行会打印出问题,应该是先执行关闭线程操作了
//        executor.shutdown();
    }
}

执行结果:

时间:2019-05-30 03:33:19
时间:2019-05-30 03:33:21 线程pool-1-thread-2 执行了task: task-0
时间:2019-05-30 03:33:21 线程pool-1-thread-1 执行了task: task-1
时间:2019-05-30 03:33:26 线程pool-1-thread-2 执行了task: task-2
时间:2019-05-30 03:33:26 线程pool-1-thread-1 执行了task: task-3
时间:2019-05-30 03:33:31 线程pool-1-thread-2 执行了task: task-4
时间:2019-05-30 03:33:31 线程pool-1-thread-1 执行了task: task-5
时间:2019-05-30 03:33:36 线程pool-1-thread-2 执行了task: task-6
时间:2019-05-30 03:33:36 线程pool-1-thread-1 执行了task: task-7
时间:2019-05-30 03:33:40 线程pool-1-thread-2 执行了task: task-8

 

scheduleWithFixedDelay方法:

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                             long initialDelay,
                             long delay,
                             TimeUnit unit);
command:执行的任务 Callable或Runnable接口实现类

initialDelay:第一次执行任务延迟时间
period:连续执行任务之间的周期,从上一个任务全部执行完成时计算延迟多少开始执行下一个任务
unit:initialDelay和period时间单位

final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        executor.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                System.out.println("时间:" + sf.format(new Date()) );
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },  2, 3, TimeUnit.SECONDS);
输出结果: 
时间:2014-04-01 23:47:38
时间:2014-04-01 23:47:46
时间:2014-04-01 23:47:54

执行任务案例:

package com.thread.testExtendsThread.fourPackage;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.*;

/**
 * @author liuchj
 * @version 1.0
 * @className ScheduledThreadTest
 * @description //TODO
 * @date 2019/5/30
 **/
public class ScheduledThreadTest {
    /**
     * 线程安全的队列
     */
    static Queue<String> queue = new ConcurrentLinkedQueue<String>();

    static {
        //入队列
        for (int i = 0; i < 9; i++) {
            queue.add("task-" + i);
        }
    }

    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        System.out.println("时间:" + sdf.format(new Date()) );
        for (int i = 0; i < queue.size(); i++) {
            executor.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {

                    String value = ThreadPoolTask.queue.poll();
                    if (value != "" && null != value) {
                        System.out.println("时间:" + sdf.format(new Date())+" 线程" + Thread.currentThread().getName() + " 执行了task: " + value);
                    }
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },  2, 6, TimeUnit.SECONDS);

        }
//这行代码不注释掉,任务都不能执行了,估计先执行此处关闭线程
//        executor.shutdown();
    }
}


执行结果:

时间:2019-05-30 03:54:45
时间:2019-05-30 03:54:47 线程pool-1-thread-2 执行了task: task-1
时间:2019-05-30 03:54:47 线程pool-1-thread-1 执行了task: task-0
时间:2019-05-30 03:54:52 线程pool-1-thread-1 执行了task: task-2
时间:2019-05-30 03:54:52 线程pool-1-thread-2 执行了task: task-3
时间:2019-05-30 03:54:57 线程pool-1-thread-2 执行了task: task-4
时间:2019-05-30 03:54:57 线程pool-1-thread-1 执行了task: task-5
时间:2019-05-30 03:55:02 线程pool-1-thread-1 执行了task: task-6
时间:2019-05-30 03:55:02 线程pool-1-thread-2 执行了task: task-7
时间:2019-05-30 03:55:07 线程pool-1-thread-1 执行了task: task-8


 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐