36-案例实现
案例实现
根据如下步骤实现本案例:
1.创建一个名为 ReportGenerator
的类,并实现泛型为 String
的 Callable
接口:
public class ReportGenerator implements Callable<String> {
2.声明两个名为 sender
和 title
的私有变量。这些变量将会展示报告数据:
private final String sender;
private final String title;
3.实现该类的构造方法,并初始化类中变量:
public ReportGenerator(String sender, String title){
this.sender=sender;
this.title=title;
}
4.实现 call()
方法。首先让该线程随机休眠一段时间:
@Override
public String call() throws Exception {
try {
Long duration=(long)(Math.random()*10);
System.out.printf("%s_%s: ReportGenerator: Generating a
report during %d seconds\n",this.sender,
this.title,duration);
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
5.用 sender
变量和 title
变量来生成一个 String
类型的报告并返回值:
String ret=sender+": "+title;
return ret;
}
6.创建一个名为 ReportRequest
的类,并实现 Runnable
接口。该类将模拟一些报告请求:
public class ReportRequest implements Runnable {
7.声明一个名为 name
的私有 String
型变量,用来存储 ReportRequest的
名称:
private final String name;
8.声明一个名为 service
的私有 CompletionService
型变量。该 Completion- Service
接口的泛型为 String
:
private final CompletionService<String> service;
9.实现该类的构造方法,并初始化类中变量:
public ReportRequest(String name, CompletionService<String>
service){
this.name=name;
this.service=service;
}
10.实现 run()
方法。创建3个 ReportGenerator
实例对象并使用 submit()
方法提交给 CompletionService
对象:
@Override
public void run() {
ReportGenerator reportGenerator=new ReportGenerator(name,
"Report");
service.submit(reportGenerator);
}
11.创建一个名为 ReportProcessor
的类,并实现 Runnable
接口。该类用来接收 Report Generator
任务返回的结果:
public class ReportProcessor implements Runnable {
12.声明一个名为 service
的私有 CompletionService
类型变量。 Completion- Service
接口的泛型为 String
:
private final CompletionService<String> service;
13.声明一个名为 end
的私有 boolean
型变量。添加 volatile
关键字来确保所有线程都可以获取到该变量的真实值:
private volatile boolean end;
14.实现该类的构造方法,并初始化类中变量:
public ReportProcessor (CompletionService<String> service){
this.service=service;
end=false;
}
15.实现 run()
方法。当变量 end
为 false
的时候,调用 CompletionService
接口的 poll()
方法来获取下一个任务已执行完成的 Future
对象:
@Override
public void run() {
while (!end){
try {
Future<String> result=service.poll(20, TimeUnit.SECONDS);
16.调用 Future
的 get()
方法获取任务的返回结果,并在控制台打印输出:
if (result!=null) {
String report=result.get();
System.out.printf("ReportReceiver: Report Received: %s\n",
report);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
System.out.printf("ReportSender: End\n");
}
17.实现 stopProcessing()
方法并覆盖 end
变量的值:
public void stopProcessing() {
this.end = true;
}
18.至此,我们可以开始实现应用程序的入口,创建包含 main()
方法的 Main
类:
public class Main {
public static void main(String[] args) {
19.用 Executors
类的 newCachedThreadPool()
方法来创建 ThreadPoolExecutor
实例对象:
ExecutorService executor=Executors.newCachedThreadPool();
20.创建 CompletionService
对象,传入之前创建的 executor
作为构造参数:
CompletionService<String> service=new
ExecutorCompletionService<>(executor);
21.创建两个 ReportRequest
实例对象,并创建线程执行它们:
ReportRequest faceRequest=new ReportRequest("Face", service);
ReportRequest onlineRequest=new ReportRequest("Online", service);
Thread faceThread=new Thread(faceRequest);
Thread onlineThread=new Thread(onlineRequest);
22.创建一个 ReportProcessor
实例对象,并创建线程执行它们:
ReportProcessor processor=new ReportProcessor(service);
Thread senderThread=new Thread(processor);
23.启动以上3个线程:
System.out.printf("Main: Starting the Threads\n");
faceThread.start();
onlineThread.start();
senderThread.start();
24.等待 ReportRequest
线程执行完成:
try {
System.out.printf("Main: Waiting for the report generators.\n");
faceThread.join();
onlineThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
25.调用 shutdown()
方法结束执行器,并用 awaitTermination()
方法等待剩余任务执行完毕:
System.out.printf("Main: Shutting down the executor.\n");
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
26.结束 ReportSender
对象的执行,设置 end
变量值为 true
:
processor.stopProcessing();
System.out.println("Main: Ends");