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

04-案例实现

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

案例实现

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

1.创建一个 MyExecutor 类,并扩展 ThreadPoolExecutor 类:

public class MyExecutor extends ThreadPoolExecutor {

2.声明一个 ConcurrentHashMap 类型的私有字段 startTimes

private final ConcurrentHashMap<Runnable, Date> startTimes;

3.实现该类的一个构造方法。在该方法中通过 super 关键字来调取父类的一个构造方法,并初始化 startTimes 字段:

public MyExecutor(int corePoolSize, int maximumPoolSize, 
                  long keepAliveTime, TimeUnit unit, 
                  BlockingQueue<Runnable> workQueue) {
  super(corePoolSize, maximumPoolSize, keepAliveTime, unit,
        workQueue);
  startTimes=new ConcurrentHashMap<>();
}

4.重写 shutdown() 方法。在控制台打印已经执行完成、正在执行以及等待执行的任务的信息。然后,通过 super 关键字来调用父类的 shutdown() 方法:

@Override
public void shutdown() {
  System.out.printf("MyExecutor: Going to shutdown.\n");
  System.out.printf("MyExecutor: Executed tasks: %d\n", 
                    getCompletedTaskCount());
  System.out.printf("MyExecutor: Running tasks: %d\n",
                    getActiveCount());
  System.out.printf("MyExecutor: Pending tasks: %d\n",
                    getQueue().size());
  super.shutdown();
}

5.重写 shutdownNow() 方法。在控制台打印已经执行完成、正在执行以及等待执行的任务的信息。然后,通过 super 关键字来调用父类的 shutdownNow() 方法:

@Override
public List<Runnable> shutdownNow() {
  System.out.printf("MyExecutor: Going to immediately 
                    shutdown.\n");
  System.out.printf("MyExecutor: Executed tasks: %d\n",
                    getCompletedTaskCount());
  System.out.printf("MyExecutor: Running tasks: %d\n",
                    getActiveCount());
  System.out.printf("MyExecutor: Pending tasks: %d\n",
                    getQueue().size());
  return super.shutdownNow();
}

6.重写 beforeExecute() 方法。在控制台打印将要执行的线程的名字及其散列码。以任务的散列码作为key,存储开始日期到 HashMap 中:

@Override
protected void beforeExecute(Thread t, Runnable r) {
  System.out.printf("MyExecutor: A task is beginning: %s : %s\n", 
                        t.getName(),r.hashCode());
  startTimes.put(r, new Date());
}

7.重写 afterExecute() 方法。在控制台打印任务的执行结果,并且使当前日期与存储在 HashMap 中的开始日期执行相减操作,以此来计算该任务的运行时间:

  @Override
  protected void afterExecute(Runnable r, Throwable t) {
    Future<?> result=(Future<?>)r;
    try {
      System.out.printf("*********************************\n");
      System.out.printf("MyExecutor: A task is finishing.\n");
      System.out.printf("MyExecutor: Result: %s\n", 
                        result.get());
      Date startDate=startTimes.remove(r);
      Date finishDate=new Date();
      long diff=finishDate.getTime()-startDate.getTime();
      System.out.printf("MyExecutor: Duration: %d\n",diff);
      System.out.printf("*********************************\n");
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
  }
}

8.创建一个实现 Callable 接口的 SleepTwoSecondsTask 类。实现其 call() 方法。使当前线程休眠2s,然后把当前时间转成 String 类型值并返回:

public class SleepTwoSecondsTask implements Callable<String> {
  public String call() throws Exception {
    TimeUnit.SECONDS.sleep(2);
    return new Date().toString();
  }
}

9.实现本案例的 Main 类的 main() 方法:

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

10.创建一个 MyExecutor 类型的 myExecutor 对象:

MyExecutor myExecutor=new MyExecutor(4, 8, 1000,
                          TimeUnit.MILLISECONDS,
                          new LinkedBlockingDeque<Runnable>());

11.创建一个 Future 类型的对象列表,用它来存储将要传递给执行器的任务的结果对象:

List<Future<String>> results=new ArrayList<>();

12.执行10个 Task 对象:

for (int i=0; i<10; i++) {
  SleepTwoSecondsTask task=new SleepTwoSecondsTask();
  Future<String> result=myExecutor.submit(task);
  results.add(result);
}

13.通过 get() 方法获取前5个任务的执行结果,并在控制台打印:

for (int i=0; i<5; i++){
  try {
    String result=results.get(i).get();
    System.out.printf("Main: Result for Task %d : %s\n", 
                      i,result);
  } catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
  }
}

14.用 shutdown() 方法来完成执行器的执行:

myExecutor.shutdown();

15.通过 get() 方法来获取后5个任务的执行结果,并在控制台打印它们:

for (int i=5; i<10; i++){
  try {
    String result=results.get(i).get();
    System.out.printf("Main: Result for Task %d : %s\n",
                      i,result);
  } catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
  }
}

16.用 awaitTermination() 方法来等待执行器完成:

try {
  myExecutor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
  e.printStackTrace();
}

17.打印一条信息来代表本程序执行完成:

System.out.printf("Main: End of the program.\n");