在多线程程序中,主要是围绕着任务的执行来展开的,所谓的任务是指一些抽象的且离散的工作单元,通过把应用程序的工作分解到多个任务中,每个任务之间有一定的事物边界,各个任务可以同时执行,从而以并发的形式来提高执行效率

编写并发程序的时候,首要的是找到清晰的任务边界,各个任务之间应该是相互独立的。独立性有助于并发,只有有足够的资源(计算资源以及存储资源)的情况下,这些任务是可以并行执行的。例如在web服务器中,可以以独立的客户请求作为任务的边界,为不同的请求建立不同的线程来进行响应。

应用程序可以通过多种策略来调度任务的执行:

1.串行的执行任务。

在单个线程中穿行执行用户的请求,这种做法最为简单,但是其效率不如人意。

ServerSocket socket = new ServerSocket(80);
while(true){
    Socket connection = socket.accept();
    handleRequest(connection);
}

2.显示的为任务创建线程

为每个请求创建一个单独的线程进行处理。

ServerSocket socket = new ServerSocket(80);
while(true){
    final Socket connection = socket.accept();
    Runnable task = new Runnable(){
         public void run(){
            handleRequest(connection);
        }
    };
    new Thread(task).start();
}

上面的列子将请求的处理放在单独的线程中进行执行,从而可以再主线程中更快的接受其他用户的请求,从而提高了程序的吞吐量,因为会有多个线程调用handleRequest(Socket)方法,所以必须保证该方法的线程安全性。

该方式的缺点:

1。线程的生命周期开销是非常高的,每个请求创建一个线程,请求处理完之后释放线程,线程的请求和释放都会消耗大量的资源,如果在请求的到达率非常高而请求处理的过程却是轻量级的时候,大部分的资源都被消耗在创建于销毁线程上面。

2.资源的消耗,活跃的线程会消耗系统的资源,尤其是内存如果可运行线程的数量大大多于可用处理器的数量,那么有些线程就会被闲置,占用大量的内存,如果现有的线程已经保持了处理器的繁忙,那么再添加过多的线程不会增加性能,反而会降低性能,因为这些线程竞争处理器资源的时候会消耗更多的性能。

3.线程池

维护一定数量的线程,当任务到达的时候,在池中取一个空闲的线程,运行该任务,如果该任务正常的完成,那么任务完成之后该线程被返回线程池中等待下一个任务的到来,这种方式避免了创建线程以及销毁线程的开销。

java类库中对线程池的实现提供了实现,在java.util.concurrent包中提供了Executor框架,该框架中用Executor接口代替Thread对任务的执行进行抽象。

public interface Executor{
	void execute(Runnable command);
}


可以通过Executors中的静态工厂方法之一来创建一个线程池

1.newFixedThreadPool:该方法将创建一个固定大小的线程池,初始化大小为0,之后每接受一个任务就新建一个线程知道到达最大的线程数目,此时线程的数量不在变化。

2.newCachedThreadPool:如果线程的规模超过了需求的时候,那么回收空闲的线程,当需求增加的时候新建新的线程,线程的最大数目没有限制。

3.newSingleThreadExecutor:创建单个线程线性执行任务

4.newScheduledThreadPool:创建一个固定长度的线程池,以延迟或者定时的方式来执行任务。

Executor的生命周期:

public interface ExecutorService extends Executor{
	//shutdown()方法平缓的关闭线程池,不在接受新的任务,等待已经执行或者等待执行的任务执行完毕
	void shutdown();
	//采用粗暴的关闭方法,试图关闭所有运行中的任务,且等待队列中的任务不在执行。
	List<Runnable> shutdownNow();
	boolean isShutdown();
	boolean isTerminated();
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
	<T> Future<T> submit(Callable<T> task);
//接收一个Callable集合,接收一个一一对应的Future集合
	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit) throws InterruptedException;
}