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");