梧州建设网站,现在的网站开发都用什么开发,论坛企业推广,wordpress调用多媒体一#xff0c;定时器
定时器作用#xff1a;约定一个时间间隔#xff0c;时间到达后#xff0c;执行某段代码逻辑。实际上就是一个 闹钟 。
1.1使用标准库中的定时器
标准库中提供了一个 Timer 类. Timer 类的核心方法为 schedule .Timer 类中含有一个扫描线…一定时器
定时器作用约定一个时间间隔时间到达后执行某段代码逻辑。实际上就是一个 闹钟 。
1.1使用标准库中的定时器
标准库中提供了一个 Timer 类. Timer 类的核心方法为 schedule .Timer 类中含有一个扫描线程观察是否有任务到达执行时间schedule 包含两个参数. 第一个参数指定即将要执行的任务代码, 第二个参数指定多长时间之后执行 (单位为毫秒)TimerTask 类继承了 Runnable 接口所以能重写 run() 方法
public class Test {public static void main(String[] args) {Timer timer new Timer();timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(1111);}},1000);}
} 这是因为 Timer 内部的线程阻止了 进程 的结束在 Timer 中是可以安排多个任务的我们下面实现的时候要注意这一点。
1.2 定时器的实现 1. Timer 中需要一个扫描线程来扫描任务是否到时间可否执行。 2. Timer 可以安排多个任务执行而每个任务的执行时间又不一样所以我们需要使用优先级队列来存储任务让这些任务按时间顺序排列。 3. 还需要创建一个类通过类来描述一个任务包含任务的内容和时间 class MyTimer{private PriorityQueueMyTimerTask priorityQueue new PriorityQueue();public MyTimer(){//扫描线程Thread t new Thread(() - {while(true){synchronized (this){//涉及到修改操作加锁try{while(priorityQueue.isEmpty()){this.wait();}MyTimerTask myTimerTask priorityQueue.peek();long curTime System.currentTimeMillis();//得到当前时间if(curTime myTimerTask.getTime()){//到达执行时间myTimerTask.getRunnable().run();priorityQueue.poll();}else {//未到达执行时间this.wait(myTimerTask.getTime() - curTime);//线程等待//如果没有这句代码就会出现忙等类似于一直在看表}}catch (InterruptedException e){e.printStackTrace();}}}});t.start();}public void schedule(Runnable runnable, long delay){synchronized (this){MyTimerTask myTimerTask new MyTimerTask(runnable,delay);priorityQueue.offer(myTimerTask);//将任务放入队列this.notify();//如果当前队列为空唤醒线程}}
}class MyTimerTask implements ComparableMyTimerTask{private Runnable runnable;//任务内容private long time;//任务执行的具体时间public MyTimerTask(Runnable runnable, long delay){this.time System.currentTimeMillis() delay;this.runnable runnable;}//得到任务执行的时间public long getTime(){return time;}//得到任务内容public Runnable getRunnable() {return runnable;}//重写比较方法按照时间顺序从小到大排列Overridepublic int compareTo(MyTimerTask o) {return (int) (this.time - o.time);}
} 关于上述代码还有几个细节需要注意 1. 因为 wait() 也可能会被InterruptedException打断如果使用 if 这时候队列仍然为null就不能出现错误。 2. 因为如果使用sleep有一种场景是不能成立的就是当我们插入一个执行时间更早的任务时线程还是处于休眠状态这时候新插入的任务就会延迟执行这不符合我们的逻辑。 而使用 wait 的话线程就会重新去找那个最先执行的任务。 二线程池
线程池能够减少线程创建和销毁的开销也就是说适用于线程频繁创建销毁的场景。
2.1 使用标准库中的线程池
Executors 创建线程池的几种方式
newFixedThreadPool: 创建固定线程数的线程池newCachedThreadPool: 创建线程数目动态增长的线程池线程执行完后不会立即销毁而是会缓存一段时间newSingleThreadExecutor: 创建只包含单个线程的线程池.newScheduledThreadPool: 设定 延迟时间后执行命令或者定期执行命令. 是进阶版的 Timer.
public class Demo {public static void main(String[] args) {ExecutorService service Executors.newCachedThreadPool();ExecutorService service1 Executors.newFixedThreadPool(3);ExecutorService service2 Executors.newSingleThreadExecutor();ExecutorService service3 Executors.newScheduledThreadPool(2);service.submit(new Runnable() {//通过 ExecutorService.submit 可以注册一个任务到线程池Overridepublic void run() {System.out.println(111);}});}
}
这里为什么不使用 new 的方法来创建一个线程池而是使用 工厂模式 来实现呢
首先了解一下什么是工厂模式工厂模式是指使用普通方法来代替构造方法完成初始化工作因为普通方法可以通过方法名来区分也就不用受到重载规则的限制。比如我们的坐标既可以使用笛卡尔坐标系也可以使用极坐标系这两个构造方法的参数是完全相同的这时候我们就要使用 工厂模式 来初始化。
Executors 本质上是 ThreadPoolExecutor 类的封装ThreadPoolExecutor 提供了更多的可选参数, 可以进一步细化线程池行为的设定。下面我们来介绍一下构造方法的参数(很重要)。 corePoolSize : 线程池最少有多少线程maximumPoolSize : 线程池最多有多少线程keepAliverTime : 线程有多长的 摸鱼 时间如果一个线程有 keepAliverTime 个时间没有工作那么就会销毁该线程。unit : keepAliverTime 的单位workQueue 阻塞队列如果需要优先级就设置 PriorityBlockingQueue如果有数量限制就设置 ArrayBlockingQueue如果数目变动较大就设置 LinkedBlockingQueuethreadFactory 工厂模式使用工厂模式来创建线程设置一些线程的属性handler 线程池的拒绝策略一个线程池容纳的任务数量是有上限的当到达上限后继续添加线程的处理方式处理的4种方式如下 这里还有一道经典的面试题如果使用线程池需要设定线程的数目设置成多少合适 这个时候只要回答出具体的数字就错的因为一个线程执行的代码有两类 1cpu 密集型代码主要进行算术运算 / 逻辑运算 2IO 密集型代码主要进行 IO 操作 假设一个线程的所有代码都是 cpu 密集型这时候线程池的线程数量不应该超过 N cpu 逻辑核心数大于 N也无法提高效率。 假设一个线程的所有代码都是 IO 密集型这时候不吃 cpu这时候就可以超过 N. 代码不同一个线程池的线程数量设置就不同因为我们无法知道一段代码有多少是cpu密集型多少是 IO 密集型。正确的回答是使用实验的方式对程序进行性能测试在测试过程中不段的调整线程池的线程数量看哪种情况更符合要求。 2.2 线程池的简单实现
import java.util.concurrent.*;class MyThreadPool{BlockingQueueRunnable blockingQueue new ArrayBlockingQueue(4);public void submit(Runnable runnable){try {blockingQueue.put(runnable);} catch (InterruptedException e) {throw new RuntimeException(e);}}public MyThreadPool(int n){for (int i 0; i n; i) {Thread t new Thread(()-{try {Runnable a blockingQueue.take();a.run();} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}}
}