zoukankan      html  css  js  c++  java
  • Timer与TimerTask之二:timer使用缺陷及用ScheduledThreadPoolExecutor解决

    1.缺陷一:Timer由于内部只要一个线程,管理多个任务的时候,一个任务延时,后面的任务就会跟着延时。用下面的例子说明:

    package com.dxz.timer;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TimerTaskTest {
        private static long startTime;
    
        public static void main(String[] args) {
    
            // 创建一个定时task1
            TimerTask task1 = new TimerTask() {
    
                @Override
                public void run() {
                    System.out.println("task1 excude ..." + (System.currentTimeMillis() - startTime));
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            // 创建一个定时task2
            TimerTask task2 = new TimerTask() {
    
                @Override
                public void run() {
                    System.out.println("task2 excude ..." + (System.currentTimeMillis() - startTime));
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
    
            Timer timer = new Timer("TimerThread");
            startTime = System.currentTimeMillis();
            // 第1个任务1s后,执行
            timer.schedule(task1, 1000);
            // 第2个任务3s后,执行
            timer.schedule(task2, 3000);
    
        }
    
    }

    结果:

    task1 excude ...1001
    task2 excude ...4002

    从上面的代码看出,第一个任务1s后执行,第二个任务3s后执行。实际上task2是在4s后才执行的,因为Timer内部是一个线程,而task1所需的时间超过了两个任务的间隔时间导致。下面使用ScheduledThreadPool解决上面的问题:

    package com.dxz.timer;
    
    import java.util.TimerTask;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class ScheduledThreadPoolTest1 {
    
        private static long startTime;
    
        public static void main(String[] args) {
            ScheduledExecutorService newExecutorService = Executors.newScheduledThreadPool(2);
    
            // 创建一个定时task1
            TimerTask task1 = new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " excude ..."
                            + (System.currentTimeMillis() - startTime) + "ms");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            // 创建一个定时task2
            TimerTask task2 = new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " excude ..."
                            + (System.currentTimeMillis() - startTime) + "ms");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
    
            startTime = System.currentTimeMillis();
            // 第1个任务1000 表示1s后,执行
            newExecutorService.schedule(task1, 1000, TimeUnit.MILLISECONDS);
            // 第2个任务3000 表示3s后,执行
            newExecutorService.schedule(task2, 3000, TimeUnit.MILLISECONDS);
    
        }
    
    }

    结果:

    pool-1-thread-1 excude ...1001ms
    pool-1-thread-2 excude ...3002ms

    2、缺陷二:

    package com.dxz.timer;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TimerTaskTest2 {
        private static long startTime;
    
        public static void main(String[] args) {
            // 创建一个定时task1
            TimerTask task1 = new TimerTask() {
                @Override
                public void run() {
                    throw new RuntimeException("运行时异常");
                }
            };
            // 创建一个定时task2
            TimerTask task2 = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("task2 excude ..." + (System.currentTimeMillis() - startTime));
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
    
            Timer timer = new Timer("TimerThread");
            startTime = System.currentTimeMillis();
            timer.schedule(task1, 100);
            timer.scheduleAtFixedRate(task2, new Date(), 1000);
    
        }
    
    }

    结果:

    task2 excude ...2
    Exception in thread "TimerThread" java.lang.RuntimeException: 运行时异常
        at com.dxz.timer.TimerTaskTest2$1.run(TimerTaskTest2.java:15)
        at java.util.TimerThread.mainLoop(Timer.java:555)
        at java.util.TimerThread.run(Timer.java:505)

    使用ScheduledExecutorService来解决:

    package com.dxz.timer;
    import java.util.TimerTask;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class ScheduledThreadPoolTest2 {
    
        private static long startTime;
    
        public static void main(String[] args) {
            ScheduledExecutorService newExecutorService = Executors.newScheduledThreadPool(1);
    
            // 创建一个定时task1
            TimerTask task1 = new TimerTask() {
                @Override
                public void run() {
                    new RuntimeException();
                }
            };
            // 创建一个定时task2
            TimerTask task2 = new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " excude ..." + (System.currentTimeMillis() - startTime) + "ms");
                }
            };
    
            startTime = System.currentTimeMillis();
            newExecutorService.schedule(task1, 0, TimeUnit.MILLISECONDS);
            // 第2个任务3000 表示3s后,执行
            newExecutorService.scheduleAtFixedRate(task2,1000, 1000, TimeUnit.MILLISECONDS);
    
        }
    
    }

    结果:

    pool-1-thread-1 excude ...1002ms
    pool-1-thread-1 excude ...2001ms
    pool-1-thread-1 excude ...3002ms
    pool-1-thread-1 excude ...4002ms
  • 相关阅读:
    vue+layui制作列表页
    基础JQ框架
    MVC返回数据流,ajax接受并保存文件
    js验证表单
    jq扩展获取表单值、设置值
    常用sql记录
    JSON
    JS和JQUERY的区别
    用面向对象的方式进行数据访问
    win7旗舰版梦幻主题补丁~完美你的桌面
  • 原文地址:https://www.cnblogs.com/duanxz/p/2769616.html
Copyright © 2011-2022 走看看