0
点赞
收藏
分享

微信扫一扫

6.定时器和线程池

小布_cvg 2022-05-05 阅读 96
java-ee

目录

一、定时器

1. Java.util包下的Timer类---“闹钟”

1.1 schedule(TimeTask task,long delay)方法

1.2 schedule(TimeTask task,long delay,long period)方法 

2. Java.util包下的TimerTask抽象类---指定需要执行的任务

3.实现一个简易的定时器---只执行一次

3.1MyTimer类 

3.2MyTimerTask类

3.3测试1 

3.4测试2

3.5改正测试2 

二、Thread.sleep()和wait(long timeout)的区别

三、线程池


一、定时器

1. Java.util包下的Timer类---“闹钟”

1.1 schedule(TimeTask task,long delay)方法

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author happy
 */
public class UseTimer {
    public static void main(String[] args) throws InterruptedException {
    Timer timer = new Timer();      // 闹钟
    TimerTask task = new TimerTask() {  // 闹钟到时间后要做的任务
        @Override
        public void run() {
            System.out.println("闹钟响了"); //输出“闹钟响了”
        }
    };

    timer.schedule(task, 5000);

    while (true) {} // 主线程死循环,所以之后的打印,一定不是主线程打印的
}
}

1.2 schedule(TimeTask task,long delay,long period)方法 

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author happy
 */
public class UseTimer {
    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();      // 闹钟
        TimerTask task = new TimerTask() {  // 闹钟到时间后要做的任务
            @Override
            public void run() {
                System.out.println("闹钟响了");
            }
        };
        // 1秒之后,每隔2秒打印一次“闹钟响了”
        timer.scheduleAtFixedRate(task, 1000, 2000);

        while (true) {
        } // 主线程死循环,所以之后的打印,一定不是主线程打印的
    }
}

2. Java.util包下的TimerTask抽象类---指定需要执行的任务

 3.实现一个简易的定时器---只执行一次

3.1MyTimer类 

import java.util.concurrent.PriorityBlockingQueue;

/**
 * @author happy
 */
public class MyTimer {
    // 这里是普通属性,不是静态属性
    private final PriorityBlockingQueue<MyTimerTask> queue = new PriorityBlockingQueue<>();

    public MyTimer() {
        Worker worker = new Worker();
        worker.start();
    }

    // 不能使用静态内部类,否则看不到外部类的属性
    class Worker extends Thread {
        @Override
        public void run() {
            while (true) {
                MyTimerTask task = null;
                try {
                    task = queue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // task 应该有个应该执行的时刻(不能记录 delay)
                long now = System.currentTimeMillis();
                // now是现在的时间
                // task.runAt是需要在什么时刻执行的时间
                // delay是需要休眠多长时间
                long delay = task.runAt - now;
                if (delay <= 0) {
                    task.run();
                } else {
                    try {
                        Thread.sleep(delay);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    task.run();
                }
            }
        }
    }

    public void schedule(MyTimerTask task, long delay) {
        // 该方法非工作线程调用
        task.runAt = System.currentTimeMillis() + delay;
        queue.put(task);
    }
}

3.2MyTimerTask类

/**
 * @author happy
 */
public abstract class MyTimerTask implements Comparable<MyTimerTask> {
    // 优先级队列,要求元素具备比较能力
    // runAt越小说明应该越先执行
    long runAt;     // 这个任务应该在何时运行(记录为 ms 为单位的时间戳)

    abstract public void run();


    @Override
    public int compareTo(MyTimerTask o) {
        if (runAt < o.runAt) {
            return -1;
        } else if (runAt > o.runAt) {
            return 1;
        } else {
            return 0;
        }
    }
}

3.3测试1 

public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyTimerTask t1 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("5s 之后");
            }
        };

        MyTimerTask t2 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("4s 之后");
            }
        };

        MyTimerTask t3 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("3s 之后");
            }
        };

        MyTimerTask t4 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("2s 之后");
            }
        };

        MyTimerTask t5 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("1s 之后");
            }
        };


        MyTimer myTimer = new MyTimer();
        myTimer.schedule(t1, 5000);
        myTimer.schedule(t2, 4000);
        myTimer.schedule(t3, 3000);
        myTimer.schedule(t4, 2000);
        myTimer.schedule(t5, 1000);

    }
}

3.4测试2

public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyTimerTask t1 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("5s 之后");
            }
        };

        MyTimerTask t2 = new MyTimerTask() {
            @Override
            public void run() {
                System.out.println("1.5s 之后");
            }
        };

        MyTimer myTimer = new MyTimer();
        myTimer.schedule(t1, 5000);

        TimeUnit.SECONDS.sleep(1);
        myTimer.schedule(t2, 1500);

    }
}

3.5改正测试2 

import java.util.concurrent.PriorityBlockingQueue;

/**
 * @author happy
 */
public class MyTimer {
    // 这里是普通属性,不是静态属性
    private final PriorityBlockingQueue<MyTimerTask> queue = new PriorityBlockingQueue<>();
    private final Object newTaskComing = new Object();


    public MyTimer() {
        Worker worker = new Worker();
        worker.start();
    }

    // 不能使用静态内部类,否则看不到外部类的属性
    class Worker extends Thread {
        @Override
        public void run() {
            while (true) {
                MyTimerTask task = null;
                try {
                    task = queue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // task 应该有个应该执行的时刻(不能记录 delay)
                long now = System.currentTimeMillis();
                // now是现在的时间
                // task.runAt是需要在什么时刻执行的时间
                // delay是需要休眠多长时间
                long delay = task.runAt - now;
                if (delay <= 0) {
                    task.run();
                }else {
                    try {
                        // 应该在两种条件下醒来:
                        // 1. 有新的任务过来了(任务可能比当前最小的任务更靠前)
                        // 2. 没有新任务来,但到了该执行该任务的时候了
                        synchronized (newTaskComing) {
                            newTaskComing.wait(delay);
                        }

                        // 如果发现新任务需要执行的时间在当前时间之前
                        // 说明需要先执行新任务
                        // 如果不是,就先把新任务放回到队列中,重新取最小的任务
                        if (System.currentTimeMillis() >= task.runAt) {
                            task.run();
                        } else {
                            queue.put(task);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void schedule(MyTimerTask task, long delay) {
        // 该方法非工作线程调用
        task.runAt = System.currentTimeMillis() + delay;
        queue.put(task);
        synchronized (newTaskComing) {
            newTaskComing.notify();
        }
    }
}

二、Thread.sleep()和wait(long timeout)的区别

三、线程池

举报

相关推荐

0 条评论