废话开篇
今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文。今天主要学习的是任务执行章节,主要讲了任务执行定义、Executor、线程池和Executor生命周期等内容,大部分是概念性的,请选择阅读。
切入正题
线程中执行任务
线程执行任务的两种策略:一是把所有的任务放在单个线程中串行执行,二是将每个任务放在各自的线程中执行。策略一的问题在于其糟糕的响应性和吞吐量;策略二的问题在于资源管理的复杂性。
Executor框架
Executor简化了线程的管理工作,并且java.util.concurrent提供了一种灵活的线程池作为Executor框架的一部分。Executor基于生产者—消费者设计模式,提交任务的操作单元相当于生产者(生成待完成的工作单元),执行任务的线程相当于消费者(执行完这些工作单元)。
示例代码:TaskExecutionWebServer
1 /** 2 * @Title: TaskExecutionWebServer.java 3 * @Package never.chapter06 4 * @author "Never" xzllc2010#gmail.com 5 * @date Mar 15, 2014 9:16:26 AM 6 * @Description: TODO 7 */ 8 package never.chapter06; 9 10 import java.io.IOException; 11 import java.net.ServerSocket; 12 import java.net.Socket; 13 import java.util.concurrent.Executor; 14 import java.util.concurrent.Executors; 15 16 public class TaskExecutionWebServer { 17 private static final int NTHREADS = 100; 18 private static final Executor exec = Executors.newFixedThreadPool(NTHREADS); 19 20 public static void main(String[] args) throws IOException { 21 ServerSocket serverSocket = new ServerSocket(80); 22 while (true) { 23 final Socket connection = serverSocket.accept(); 24 Runnable task = new Runnable() { 25 public void run() { 26 // handleRequest(connection); 27 } 28 }; 29 exec.execute(task); 30 } 31 } 32 }
线程池
从字面上来看,是指管理一组同构工作线程的资源池。在线程池中执行任务比为每一个任务分配一个线程优势更多:不仅可以在处理多个请求时分摊在线程创建和销毁过程中产生的巨大开销,另外一个好处就是当请求到达时,工作线程通常已经存在,因此不会由于等待线程创建而延迟任务的执行。Java类库提供了四种线程池以满足不同的任务执行需求:
newFixedThreadPool:固定长度的线程池,即线程池的规模有上限。
newCachedThreadPool:可缓存的线程池,如果线程池的当前规模超过了处理需求时,将回收空闲的线程,而当需求增加时,则可以添加新的线程,注意线程池的规模不存在任何限制。
newSingleThreadExecutor:单线程的Executor,通过创建单个工作者线程来串行的执行任务,如果此线程异常结束,Executor会创建另一个线程来代替。注意此模式能确保依照任务在队列中的顺序来串行执行(例如FIFO、LIFO、优先级)。
newScheduledThreadPool:创建固定长度的线程池,而且以延迟或者定时的方式来执行任务。
Executor的生命周期
Executor的实现通常会创建线程来执行任务,但JVM只有在所有(非守护)线程全部终止后才会退出,因此,如果无法正确地关闭Executor,那么JVM将无法结束。为了解决执行服务的生命周期问题,ExecutorService扩展了Executor接口,添加了管理生命周期的方法。ExecutorService的生命周期主要有三种状态:运行、关闭和已终止。
路漫漫其修远兮,吾将上下而求索
今天写到这,随后会对上面的内容展开详细的介绍。