java线程池介绍(java并发编程实战第6章)

为什么需要使用线程池? one-thread-per-request可能带来的问题:

1. 线程的创建和销毁会占用一定的资源. 如果请求频繁而对请求的处理是轻量级的(大多的web请求符合该情形), 创建一个线程处理请求后将其销毁的方式是不划算的.

2. 过多的线程导致线程切换频繁, 用于处理请求的CPU时间反而会减少. 如果当前的线程数已经让CPU处于忙碌状态, 那么增加更多的线程不会改善应用的性能. 

3. 过多的线程会导致系统稳定性下降. 

综上, 我们需要考虑将创建好的线程组织成线程池, 当请求来临时从池中取出线程处理请求, 处理完毕后将线程归还给线程池, 而不是销毁. 另外我们可以限制线程池中的线程数, 以克服线程过多时性能和稳定性下降的缺陷.

 

Executor

java的Executor Framework包含多个线程池的实现, 所有线程池都派生自Executor接口. Executor接口只定义了一个方法: execute(Runnable task). Executor接口解耦了任务提交和任务执行. Executor接口是基于生产者消费者模式实现的, 提交任务的线程为生产者, 执行任务的线程为消费者. 使用示例:

Java代码   收藏代码
  1. class TaskExecutionWebServer {   
  2.     private static final int NTHREADS = 100;   
  3.     // 创建线程池  
  4.     private static final Executor exec   
  5.         = Executors.newFixedThreadPool(NTHREADS);   
  6.    
  7.     public static void main(String[] args) throws IOException {   
  8.         ServerSocket socket = new ServerSocket(80);   
  9.         while (true) {   
  10.             final Socket connection = socket.accept();   
  11.             Runnable task = new Runnable() {   
  12.                 public void run() {   
  13.                     handleRequest(connection);   
  14.                 }   
  15.             };   
  16.         // 将任务提交给线程池执行  
  17.             exec.execute(task);   
  18.         }   
  19.     }   
  20. }  
  

ExecutorService和线程池的具体实现

ExecutorService接口继承自Executor, 而预定义的线程池类大多实现了ExecutorService接口.

调用Executors类的静态方法可以获取预定义的线程池:

1. newFixedThreadPool. 调用该方法创建最大线程数固定的线程池.

2. newCachedThreadPool. 调用该方法创建可伸缩式线程池, 当线程池中线程的数量超过程序所需时, 会自动销毁多余的线程; 当线程池中的线程不能需要时再创建新的线程执行提交的任务. 该线程池没有最大线程数的限定.

3. newSingleThreadExecutor. 调用该方法创建仅包含一个线程的线程池, 提交给该线程池执行的任务, 都将在这一单个线程中完成处理.

4. newScheduledThreadPool. 调用该方法创建最大线程数固定且支持延迟和周期性重复执行任务的线程池.

ExecutorService接口提供了一些生命周期管理的方法:

1. 关闭线程池. shutdown()方法在关闭前允许执行以前提交的任务, 包括那些已提交但尚未开始执行的任务. 而shutdownNow()方法阻止尚未开始执行的任务启动并试图停止当前正在执行的任务, 返回从未开始执行的任务的列表. 线程池关闭后将拒绝接受新任务, isShutdown()可用于判断线程池是否已关闭.

2. 当线程池已关闭, 并且所有提交给线程池的任务都已完成时, 线程池转变为终止状态. 调用ExecutorService的awaitTermination方法, 将使得当前线程阻塞, 直到线程池转变为终止状态. 通常在调用shutdown方法后紧接着调用awaitTermination方法. isTerminated()用于检测线程池是否处于终止状态. 

使用ExecutorService的例子:

Java代码   收藏代码
  1. class LifecycleWebServer {   
  2.     private final ExecutorService exec = ...;   
  3.    
  4.     public void start() throws IOException {   
  5.         ServerSocket socket = new ServerSocket(80);   
  6.         while (!exec.isShutdown()) {   
  7.             try {   
  8.                 final Socket conn = socket.accept();   
  9.                 exec.execute(new Runnable() {   
  10.                     public void run() { handleRequest(conn); }   
  11.                 });   
  12.             } catch (RejectedExecutionException e) {   
  13.         // 线程池关闭后提交任务将抛出RejectedExecutionException异常  
  14.                 if (!exec.isShutdown())   
  15.                     log("task submission rejected", e);   
  16.             }   
  17.         }   
  18.     }   
  19.    
  20.     public void stop() { exec.shutdown(); }   
  21.    
  22.     void handleRequest(Socket connection) {   
  23.         Request req = readRequest(connection);   
  24.     // 如果是关闭请求, 就关闭线程池, 否则分发该请求  
  25.         if (isShutdownRequest(req))   
  26.             stop();   
  27.         else   
  28.             dispatchRequest(req);   
  29.     }   
  30. }   

 

Timer和ScheduledThreadPoolExecutor的比较

两者都可以用于延时或周期性重复执行某个任务, 但是Timer存在一些缺陷:

1. Timer基于绝对时间来安排任务的调度, 因此系统时钟的改变会对其产生影响. ScheduledThreadPoolExecutor基于相对时间进行任务的调度.

2. Timer创建单一的线程执行定时任务. 假如Timer对象以10ms的间隔重复执行某个任务, 但是其中的一次执行花去了40ms, 这就意味着少执行了至少4次重复任务. ScheduledThreadPoolExecutor可以使用多个线程执行定时任务.

3. 如果在执行任务的过程中抛出运行时异常, Timer的线程会被终止且没有恢复机制. ScheduledThreadPoolExecutor对这种情形做了适当的处理.


生命周期:

为了解决执行服务的生命周期问题,ExecutorService扩展了Executor接口,添加了一些生命周期管理的方法(同时还有一些用于任务提交的便利方法)

public interface ExecutorService extends Executor {

void shutdown();

List<Runnable> shutdownNow();

boolean isShutdown();

boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

//其他用于任务提交的便利方法

}

ExecutorService的生命周期有3种状态:运行,关闭和已终止。ExecutorService在初始创建时处于运行状态。shutdown方法执行平缓

的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成---包括那些还未开始执行的任务。shutdownNow方法将执行粗暴的

关闭过程:它将尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值