定时任务(3)--ScheduledExecutorService类

来源:互联网 发布:淘宝店铺流量软件app 编辑:程序博客网 时间:2024/06/05 14:23

在前面说了两种处理方式以后,下面介绍一种最近研究jdk无意发现的一个定时任务处理器。ScheduledExecutorService和Runnable接口配合实现定时任务的方案。这是在学习多线程的时候,发现的一种实现技术。对于类的使用方法,这里不再赘述。也是直接把代码弄上来。然后再分析。



import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class ThreadPools {
    ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
    class PrintThreadAsRate implements Runnable{
        public void run() {
            System.out.println("我是以固定频率运行的" +":"+System.currentTimeMillis()+":ThreadId"+Thread.currentThread().getId());
            try {
                //表示该任务需要1.5s才能完成。
                Thread.currentThread().sleep(1500);
            } catch (InterruptedException e) {
            }
        }
    }
    class PrintThreadAsDelay implements Runnable{
        private boolean flag = false;
        public void run() {
                System.out.println("固定延迟运行"+System.currentTimeMillis()+":ThreadId"+Thread.currentThread().getId());
                try {
                    //延迟代表该任务运行时间需要2s
                    Thread.currentThread().sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    int start = 0;
    public void exeTask(int count){
        for(;start < count; start++){
            //以固定频率运行。
            ses.scheduleAtFixedRate(new PrintThreadAsRate(), 1000,1*1000,TimeUnit.MILLISECONDS);
            //以固定间隔运行。
            ses.scheduleWithFixedDelay(new PrintThreadAsDelay(), 1000,1*1000,TimeUnit.MILLISECONDS);
        }
        //由于我使用junit测试,所以这里线程等待,以保证运行,如果使用main方法测试,不需要线程睡眠等待。
        try {
            Thread.currentThread().sleep(1000*60*60);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

//我是以固定频率运行的:1408714479402:ThreadId10
//固定延迟运行1408714479403:ThreadId11
//我是以固定频率运行的:1408714480903:ThreadId10
//固定延迟运行1408714482404:ThreadId12
//我是以固定频率运行的:1408714482404:ThreadId11
//我是以固定频率运行的:1408714483905:ThreadId11
//固定延迟运行1408714485405:ThreadId12
//我是以固定频率运行的:1408714485406:ThreadId14

--------------------------------------------------------------------------------------------------------------------------------------------

代码有注释,具体的就不细说了,下面分析一下结果。由于原始数据比较乱。我们先将其整理一下。

//我是以固定频率运行的:1408714479402:ThreadId10

//我是以固定频率运行的:1408714480903:ThreadId10

//我是以固定频率运行的:1408714482404:ThreadId11
//我是以固定频率运行的:1408714483905:ThreadId11

//我是以固定频率运行的:1408714485406:ThreadId14
//固定延迟运行1408714479403:ThreadId11
//固定延迟运行1408714482404:ThreadId12
//固定延迟运行1408714485405:ThreadId12

整理完毕,我们发现以固定频率运行的任务,我们虽然设置的是一秒钟运行一次,但是实际的运行间隔确实1.5s才运行一次。

 而以固定延迟运行的任务,虽然设置的是1s执行一次,但实际上却是3s才执行一次。

我们在这里可以看出来,与Timmer相比,他们是相同的,即每个任务执行完毕后,才会执行下一次任务。不会让任务重叠执行。

再看上面的线程分配。

在Timmer类中,所有的任务在同一个线程里执行。非常的不稳定。容易出问题。

在线程实现方式上,我们为每个任务分配一个线程。如果任务执行过程中出错,并且处置不当,也很可能会挂掉。

再观察我们本文中的实现,任务的定时执行,是由线程池来分配资源。每次执行任务的线程是随机的。即使这次执行不成功,也不会影响下次执行。即使使执行线程挂掉了,线程池也会自己补充一个,不会对任务执行造成影响。

所以,如果jdk版本支持,最好还是用这种方法来实现。

好了,关于定时任务的处理,三篇博客已经全部发完了。

0 0
原创粉丝点击