Java类库中,任务执行的主要抽象不是Thread,而是Executor。Executor框架具有以下几个特点:
- 异步任务执行框架
- 基于生产者-消费者模式
- 将任务的提交过程与执行过程解耦,用runnable表示任务
- 采用不同的Executor实现即可改变服务器的行为,简化了代码修改的难度
- 支持生命周期管理、统计信息收集、应用程序管理机制和性能监视等机制。
/* @since 1.5
* @author Doug Lea
*/
public interface Executor {
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the <tt>Executor</tt> implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution.
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
}
1、几种Executor实现方式举例
package com.wenc.concurrency;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class TaskExecutionWebServer {
private static final int THREAD_NUMBER = 100;
private static final Executor exec = Executors.newFixedThreadPool(THREAD_NUMBER);
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while(true){
final Socket connection = socket.accept();
Runnable task = new Runnable(){
@Override
public void run() {
handleRequest(connection);
}
};
exec.execute(task);
}
}
}
基于线程池的web服务器
package com.wenc.concurrency;
import java.util.concurrent.Executor;
public class ThreadPerTaskExecutor implements Executor{
@Override
public void execute(Runnable command) {
new Thread(command).start();
}
}
每个请求启动一个新线程
package com.wenc.concurrency;
import java.util.concurrent.Executor;
public class WithinThreadExecutor implements Executor{
@Override
public void execute(Runnable command) {
command.run();
}
}
在当前线程中执行(单线程)
2、线程池
指管理一组同构工作线程的资源池。线程池与工作队列密切相关,其中在工作队列中保存了所有等待执行的任务。工作者线程的任务:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。
与上面的ThreadPerTaskExecutor相比,线程池有以下几个优点:
- 重用线程,免去线程创建和销毁的开销
- 无需创建线程,响应速度更快
- 通过调整线程池的大小,可以创建足够的线程以充分利用处理器资源,同时可以防止多线程相互竞争资源而使应用程序耗尽内存或失败,提高稳定性。
类库提供了常用的线程池实现:
- newFixedThreadPool,固定长度,每提交一个任务就创建一个线程,直到达到线程池最大数量。如果某个线程异常结束,那么线程池会补充一个新的线程。
- newCachedThreadPool,规模无限制,空闲回收、需要则新增线程,可缓存。
- newSingleThreadExecutor,大小为1,即,单线程。如果该线程异常结束,则会创建另一个线程来替代,可确保工作任务串行执行。
- newScheduledThreadPool,固定长度,以延迟或定时方式执行任务,类似Timer。
3、生命周期
Executor扩展了ExecutorService接口,添加了一些用于声明周期管理的方法,
public interface ExecutorService extends Executor {
/**
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
* Invocation has no additional effect if already shut down.
*
* @throws SecurityException if a security manager exists and
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
* java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
* or the security manager's <tt>checkAccess</tt> method
* denies access.
*/
void shutdown();
/**
* Attempts to stop all actively executing tasks, halts the
* processing of waiting tasks, and returns a list of the tasks that were
* awaiting execution.
*
* <p>There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. For example, typical
* implementations will cancel via {@link Thread#interrupt}, so any
* task that fails to respond to interrupts may never terminate.
*
* @return list of tasks that never commenced execution
* @throws SecurityException if a security manager exists and
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
* java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
* or the security manager's <tt>checkAccess</tt> method
* denies access.
*/
List<Runnable> shutdownNow();
/**
* Returns <tt>true</tt> if this executor has been shut down.
*
* @return <tt>true</tt> if this executor has been shut down
*/
boolean isShutdown();
/**
* Returns <tt>true</tt> if all tasks have completed following shut down.
* Note that <tt>isTerminated</tt> is never <tt>true</tt> unless
* either <tt>shutdown</tt> or <tt>shutdownNow</tt> was called first.
*
* @return <tt>true</tt> if all tasks have completed following shut down
*/
boolean isTerminated();
/**
* Blocks until all tasks have completed execution after a shutdown
* request, or the timeout occurs, or the current thread is
* interrupted, whichever happens first.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return <tt>true</tt> if this executor terminated and
* <tt>false</tt> if the timeout elapsed before termination
* @throws InterruptedException if interrupted while waiting
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
以下是一个使用ExecutorServie实现的支持关闭操作的web服务器:
package com.wenc.concurrency;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
/**
* 支持关闭操作的web服务器
* @author wenc
*
*/
public class LifeCycleWebServer {
private final ExecutorService exec = Executors.newFixedThreadPool(10);
public void start() throws IOException{
ServerSocket socket = new ServerSocket(80);
while(!exec.isShutdown()){
try{
final Socket conn = socket.accept();
exec.execute(new Runnable() {
@Override
public void run() {
handleRequest(conn);
}
});
}catch(RejectedExecutionException e){
if(!exec.isShutdown())
System.out.println("task submission rejected" + e);
}
}
}
public void stop(){
exec.shutdown();
}
void handleRequest(Socket conn){
Request req = readRequest(conn);
if(isShutdownRequest(req))
stop();
else
dispatchRequest(conn);
}
}