当前位置:嗨网首页>书籍在线阅读

16-案例实现

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

案例实现

根据如下步骤来实现本案例。

1.创建一个 Event 类并实现一个 Delayed 接口:

public class Event implements Delayed {

2.声明一个 Date 类型的私有字段 startDate

private final Date startDate;

3.实现一个构造方法来初始化字段:

public Event (Date startDate) {
  this.startDate=startDate;
}

4.实现 compareTo() 方法。该方法以 Delayed 对象作为参数,而且会返回一个当前对象与参数对象的对比值:

@Override
public int compareTo(Delayed o) {
  long result=this.getDelay(TimeUnit.NANOSECONDS)-o.getDelay
                                            (TimeUnit.NANOSECONDS);
  if (result<0) {
    return -1;
  } else if (result>0) {
    return 1;
  }
  return 0;
}

5.实现 getDelay() 方法。该方法会返回一个开始时间与激活时间的差值,并通过 TimeUnit 参数来将其转换为指定的时间单位:

public long getDelay(TimeUnit unit) {
  Date now=new Date();
  long diff=startDate.getTime()-now.getTime();
  return unit.convert(diff,TimeUnit.MILLISECONDS);
}

6.创建一个 Task 类并实现一个 Runnable 接口:

public class Task implements Runnable {

7.声明一个私有的 int型 字段 id 。该字段用于代表该 Task 实例的身份:

private final int id;

8.声明一个私有的 DelayQueue<Event> 字段 queue

private final DelayQueue<Event> queue;

9.实现该类的构造方法,并初始化字段:

public Task(int id, DelayQueue<Event> queue) {
  this.id=id;
  this.queue=queue;
}

10.实现 run() 方法。首先,计算将要生成任务的事件的当前日期对象;其次,基于字段id和当前日期对象的时间戳来计算事件对象的实际激活时间:

@Override
public void run() {
  Date now=new Date();
  Date delay=new Date();
  delay.setTime(now.getTime()+(id*1000));
  System.out.printf("Thread %s: %s\n",id,delay);

11.把100个事件对象通过 add() 方法添加到队列中:

  for (int i=0; i<100; i++) {
    Event event=new Event(delay);
    queue.add(event);
  }
}

12.实现一个 Main 类和一个 main() 方法:

public class Main {
  public static void main(String[] args) throws Exception {

13.创建一个 DelayQueue<Event> 类型的对象:

DelayQueue<Event> queue=new DelayQueue<>();

14.创建一个长度为5的线程数组,并用它存储即将要执行的任务:

Thread threads[]=new Thread[5];

15.创建5个 Task 对象并分别赋予不同的ID:

for (int i=0; i<threads.length; i++){
  Task task=new Task(i+1, queue);
  threads[i]=new Thread(task);
}

16.启动所有线程:

for (int i=0; i<threads.length; i++) {
  threads[i].start();
}

17.用 join() 方法等待所有线程最终完成:

for (int i=0; i<threads.length; i++) {
  threads[i].join();
}

18.在控制台打印队列长度。当队列长度大于0时,用 poll() 方法来获取一个 Event 对象;如果返回 null ,则阻塞当前线程500ms:

    do {
      int counter=0;
      Event event;
      do {
        event=queue.poll()
        if (event!=null) counter++;
      } while (event!=null);
      System.out.printf("At %s you have read %d events\n",
                        new Date(), counter);
      TimeUnit.MILLISECONDS.sleep(500);
    } while (queue.size()>0);
  }
}