周期性线程池newScheduledThreadPool详解

线程池支持定时以及周期性执行任务,创建一个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


 

  • 8
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
Java线程池是一种用于管理和复用线程的机制,它可以提高多线程程序的性能和效率。在Java中,线程池ThreadPoolExecutor类实现,通过设置不同的参数可以对线程池的行为进行调整。 以下是Java线程池的一些常用参数及其解释: 1. corePoolSize(核心线程数):线程池中始终保持的活动线程数,即使它们处于空闲状态。当有新任务提交时,如果活动线程数小于corePoolSize,则会创建新线程来处理任务。 2. maximumPoolSize(最大线程数):线程池中允许存在的最大线程数。当活动线程数达到maximumPoolSize并且工作队列已满时,新任务将会被拒绝。 3. keepAliveTime(线程空闲时间):当线程池中的线程数量超过corePoolSize时,多余的空闲线程在等待新任务到来时的最长等待时间。超过这个时间,空闲线程将被终止。 4. unit(时间单位):keepAliveTime的时间单位,可以是秒、毫秒、微秒等。 5. workQueue(工作队列):用于存储等待执行的任务的阻塞队列。常见的工作队列有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。 6. threadFactory(线程工厂):用于创建新线程的工厂类。可以自定义线程的名称、优先级等属性。 7. handler(拒绝策略):当线程池无法接受新任务时的处理策略。常见的拒绝策略有AbortPolicy(默认,抛出RejectedExecutionException异常)、CallerRunsPolicy(由调用线程执行任务)、DiscardPolicy(直接丢弃任务)和DiscardOldestPolicy(丢弃最旧的任务)。 这些参数可以根据实际需求进行调整,以达到最佳的线程池性能和资源利用率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

痴书先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值