Java:定时启动线程
版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。 |
这里提供两种在指定时间后启动线程的方法。一是通过java.util.concurrent.DelayQueue实现;二是通过java.util.concurrent.ScheduledThreadPoolExecutor实现。 1. java.util.concurrent.DelayQueue 类DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素。它接受实现Delayed接口的实例作为元素。 <<interface>>Delayed.java package java.util.concurrent; import java.util.*; public interface Delayed extends Comparable<Delayed> { long getDelay(TimeUnit unit); } DelayQueue队列的头部是延迟期满后保存时间最长的 Delayed 元素。当一个元素的getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于等于 0 的值时,将发生到期。 2.设计带有时间延迟特性的队列 类DelayedTasker维护一个DelayQueue<DelayedTask> queue,其中DelayedTask实现了Delayed接口,并由一个内部类定义。外部类和内部类都实现Runnable接口,对于外部类来说,它的run方法是按定义的时间先后取出队列中的任务,而这些任务即内部类的实例,内部类的run方法定义每个线程具体逻辑。 这个设计的实质是定义了一个具有时间特性的线程任务列表,而且该列表可以是任意长度的。每次添加任务时指定启动时间即可。 DelayedTasker.java package com.zj.timedtask; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import java.util.Collection; import java.util.Collections; import java.util.Random; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class DelayedTasker implements Runnable { DelayQueue<DelayedTask> queue = new DelayQueue<DelayedTask>(); public void addTask(DelayedTask e) { queue.put(e); } public void removeTask() { queue.poll(); } public Collection<DelayedTask> getAllTasks() { return Collections.unmodifiableCollection(queue); } public int getTaskQuantity() { return queue.size(); } public void run() { while (!queue.isEmpty()) try { queue.take().run(); } catch (InterruptedException e) { System.out.println("Interrupted"); } System.out.println("Finished DelayedTask"); } public static class DelayedTask implements Delayed, Runnable { private static int counter = 0; private final int id = counter++; private final int delta; private final long trigger; public DelayedTask(int delayInSeconds) { delta = delayInSeconds; trigger = System.nanoTime() + NANOSECONDS.convert(delta, SECONDS); } public long getDelay(TimeUnit unit) { return unit.convert(trigger - System.nanoTime(), NANOSECONDS); } public int compareTo(Delayed arg) { DelayedTask that = (DelayedTask) arg; if (trigger < that.trigger) return -1; if (trigger > that.trigger) return 1; return 0; } public void run() { //run all that you want to do System.out.println(this); } public String toString() { return "[" + delta + "s]" + "Task" + id; } } public static void main(String[] args) { Random rand = new Random(); ExecutorService exec = Executors.newCachedThreadPool(); DelayedTasker tasker = new DelayedTasker(); for (int i = 0; i < 10; i++) tasker.addTask(new DelayedTask(rand.nextInt(5))); exec.execute(tasker); exec.shutdown(); } } [0s]Task 1 [0s]Task 2 [0s]Task 3 [1s]Task 6 [2s]Task 5 [3s]Task 8 [4s]Task 0 [4s]Task 4 [4s]Task 7 [4s]Task 9 Finished DelayedTask 3. java.util.concurrent.ScheduledThreadPoolExecutor 该类可以另行安排在给定的延迟后运行任务(线程),或者定期(重复)执行任务。在构造子中需要知道线程池的大小。最主要的方法是: [1] schedule public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) 指定者: -接口 ScheduledExecutorService 中的 schedule; 参数: -command - 要执行的任务 ; -delay - 从现在开始延迟执行的时间 ; -unit - 延迟参数的时间单位 ; 返回: -表示挂起任务完成的 ScheduledFuture,并且其 get() 方法在完成后将返回 null。 [2] scheduleAtFixedRate public ScheduledFuture<?> scheduleAtFixedRate( Runnable command,long initialDelay,long period,TimeUnit unit) 指定者: -接口 ScheduledExecutorService 中的 scheduleAtFixedRate; 参数: -command - 要执行的任务 ; -initialDelay - 首次执行的延迟时间 ; -period - 连续执行之间的周期 ; -unit - initialDelay 和 period 参数的时间单位 ; 返回: -表示挂起任务完成的 ScheduledFuture,并且其 get() 方法在取消后将抛出异常。 4.设计带有时间延迟特性的线程执行者 类ScheduleTasked关联一个ScheduledThreadPoolExcutor,可以指定线程池的大小。通过schedule方法知道线程及延迟的时间,通过shutdown方法关闭线程池。对于具体任务(线程)的逻辑具有一定的灵活性(相比前一中设计,前一种设计必须事先定义线程的逻辑,但可以通过继承或装饰修改线程具体逻辑设计)。 ScheduleTasker.java package com.zj.timedtask; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ScheduleTasker { private int corePoolSize = 10; ScheduledThreadPoolExecutor scheduler; public ScheduleTasker() { scheduler = new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduleTasker(int quantity) { corePoolSize = quantity; scheduler = new ScheduledThreadPoolExecutor(corePoolSize); } public void schedule(Runnable event, long delay) { scheduler.schedule(event, delay, TimeUnit.SECONDS); } public void shutdown() { scheduler.shutdown(); } public static void main(String[] args) { ScheduleTasker tasker = new ScheduleTasker(); tasker.schedule(new Runnable() { public void run() { System.out.println("[1s]Task 1"); } }, 1); tasker.schedule(new Runnable() { public void run() { System.out.println("[2s]Task 2"); } }, 2); tasker.schedule(new Runnable() { public void run() { System.out.println("[4s]Task 3"); } }, 4); tasker.schedule(new Runnable() { public void run() { System.out.println("[5s]Task 4"); } }, 10); tasker.shutdown(); } } [1s]Task 1 [2s]Task 2 [4s]Task 3 [5s]Task 4 本文出自 “子 孑” 博客,转载请与作者联系! 本文出自 51CTO.COM技术博客 |



zhangjunhd
博客统计信息
热门文章
最新评论
友情链接


