使用执行器框架(Executor Framework)的第一步是创建执行器ThreadPoolExecutor对象。我们可以使用ThreadPoolExecutor提供的四个构造函数,或者使用Executors工厂方法来创建线程执行器。一旦有了执行器,我们就可以把Runnable或Callable对象发送给它去执行了。
接下来我们使用执行器来实现一个能够处理客户端请求的服务器。
首先我们创建一个任务执行线程,这个线程用来模拟处理客户端的请求任务,它首先打印线程创建和启动时间,然后随机休眠一段时间用来模拟任务处理过程,最后打印任务结束时间。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* 任务执行类
* Created by hadoop on 15/12/9.
*/
public class Task implements Runnable{
private String name;
private Date initDate;
public Task(String name) {
this.name = name;
this.initDate = new Date();
}
/**
* 任务过程
* 1. 打印任务创建时间
* 2. 打印任务开始时间
* 3. 任务随机休眠一段时间
* 4. 打印任务结束时间
*/
@Override
public void run() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.printf("%s: Task %s: Created on: %s\n",
Thread.currentThread().getName(), name, format.format(initDate));
System.out.printf("%s: Task %s: Started on: %s\n",
Thread.currentThread().getName(), name, format.format(new Date()));
long duration = (long)(Math.random() * 10);
System.out.printf("%s: Task %s: Do something duration %d Seconds\n",
Thread.currentThread().getName(), name, duration);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s: Task %s: Finished on: %s\n",
Thread.currentThread().getName(), name, format.format(new Date()));
}
}
接下来我们创建服务端Server类,用来模拟接受客户端的请求,然后启动任务线程来处理请求,在这个类中,我们是用来线程处理器ThreadPoolExecutor。在这里我们使用了Executors.newCachedThreadPool()线程执行器工厂来创建线程执行器,这个方法会返回一个ExecutorService类型的对象,因此需要将它的类型转换为ThreadPoolExecutor类型。
如果需要执行任务,那么线程池执行器就会创建一个新的线程来执行这个任务,如果任务执行完毕,线程池会回收线程,当有新的任务进来的时候,将会从线程池中获取线程来执行这个任务。当然如果一次发送过多的任务给线程执行器,那么将会造成很高的系统负载。
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 任务调度类
* 1. 启动一个线程池:(ThreadPoolExecutor) Executors.newCachedThreadPool();
* 2. 接受任务并加入到线程池中
* 3. 所有任务之行结束后关闭线程池
* Created by hadoop on 15/12/9.
*/
public class Server {
ThreadPoolExecutor executor;
public Server() {
executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
}
/**
* 执行任务并打印当前线程池状态
* @param task 任务
*/
public void execute(Task task) {
System.out.println("Server: A new task has arrived.\n");
executor.execute(task);
//返回线程池中的线程数
System.out.printf("Server: Pool Size: %d\n", executor.getPoolSize());
//返回线程池中正在运行的线程数
System.out.printf("Server: Active Count: %d\n", executor.getActiveCount());
//返回线程池中已经完成的任务数
System.out.printf("Server: Completed Task: %d\n", executor.getCompletedTaskCount());
}
public void endServer() {
executor.shutdown();
}
}
最后创建主类Main,并运行程序。
public class Main {
/**
* 创建10个任务并发送到线程池中
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Server server = new Server();
for (int i = 0; i < 10; i++) {
Task task = new Task("Task" + i);
server.execute(task);
Thread.sleep(1000);
}
server.endServer();
}
}