Java并发之线程池的使用浅析

   当系统并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要消耗大量的系统资源。

  所以需要一个办法使得线程可以复用,即当线程执行完一个任务,并不被销毁,而是可以继续执行其他的任务。在Java中就可以通过线程池来实现这样的效果。本文讲述了Java中的线程池类以及如何使用线程池。

一、java中的线程池ThreadPoolExecutor

   ThreadPoolExecutor是线程池中基础类也是最为核心的类。想要了解和合理使用线程池绕不开ThreadPoolExecutor类。下面介绍一下此类。

该类的构造函数如下

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { //... }

线程池有这么几个重要的参数

corePoolSize: 线程池里的核心线程数量

maximumPoolSize: 线程池里允许有的最大线程数量

keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。 默认情况下,如果当前线程数量 > corePoolSize,多出来的线程会在keepAliveTime之后就被释放掉,直到线程池中的线程数不大于corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0

unit: keepAliveTime的时间单位,有7种单位

TimeUnit.DAYS; // TimeUnit.HOURS; //小时 TimeUnit.MINUTES; //分钟 TimeUnit.SECONDS; // TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙 TimeUnit.NANOSECONDS; //

workQueue: 队列workQueue的类型为BlockingQueue<Runnable>,通常可以取下面三种类型:

有界任务队列ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小; 

无界任务队列LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;

直接提交队列synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。如果进程数量已经达到最大值,则执行拒绝策略。因此使用该队列需要设置很大的maximumPoolSize,否则很容易执行拒绝策略。

threadFactory: 每当需要创建新的线程放入线程池的时候,就是通过这个线程工厂来创建的

handler: 就是说当线程,队列都满了,之后采取的策略,比如抛出异常等策略

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,不做任何处理

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

二、 线程池中重要的方法 

线程池有两个重要的操作,提交任务和关闭线程池。在讲述这两个操作之前先了解一下线程池的状态。注意!!!,线程池的状态而不是线程状态。

在ThreadPoolExecutor中定义了一个volatile变量,另外定义了几个static final变量表示线程池的各个状态:

//当前线程池的状态,voliate 保证了线程之间的可见 volatile int runState; //创建线程池后,初始时,线程池处于此状态 static final int RUNNING = 0; /*调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕*/ static final int SHUTDOWN = 1; /*调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务*/ static final int STOP = 2; /*线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态*/ static final int TERMINATED = 3;

2.1 线程池提交任务

ThreadPoolExecutor的提交操作可以使用submit和execute这两种方法

2.1.1 excute

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d361b8ecd1f70068552bee0deb3f2ba9.html