最近Team在整理Code Review的一些Alignment。也看了下《阿里巴巴Java开发手册》,其中提到了线程和线程池的使用。这里简单整理下,可能没有条理。值得说一下,阿里也给出了一个在线编码规范的在线认证,有兴趣的可以试下。
《阿里巴巴Java开发手册》在《并发处理》部分,有这样两条涉及线程池:
3.[强制]线程资源必须通过线程池提供,不允许在应用中自行显示创建线程。允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
我们知道创建线程有三种方式:Thread、Runnable和线程池。前两者使用起来相对简单,而线程池在一个系统内部使用时就需要加倍小心了。
先看下线程池中最核心的一个类:java.uitl.concurrent.ThreadPoolExecutor。该类是深入了解Java中的线程池的关键。下边是它提供的四个可用构造函数。
public class ThreadPoolExecutor extends AbstractExecutorService {
// ...
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory) {}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
RejectedExecutionHandler handler) {}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
}
上边构造函数用到的一些参数都是为线程池配置的参数:
corePoolSize:核心池的大小。默认情况下,当任务到来才创建线程并去执行任务。之后如果程池中的线程数达到corePoolSize,就把后续到达的任务放到缓存队列当。先说下线程的状态。在Java中,线程的状态只能是下边五中状态中的一种。这点跟操作系统的线程状态有点不一样。
新建(New):创建后尚未启动的线程处于这种状态。(未调用start方法)
运行(Runable):包括操作系统线程状态中的Running和Ready。也就是说,该状态下,该线程有可能正在执行,也有可能等待CPU的时间片。
无限期等待(Waiting):该状态下,线程不会被分配CPU时间片。等待被其他线程显式地唤醒。
限期等待(Time Waiting):该状态下,线程也不会被分配CPU时间片。跟无限期等待不一样的是,在一定时间之后,它们会由系统自动唤醒,无须等待其他线程显式唤醒。
阻塞(Blocked):线程被阻塞了。等待获取一个排他锁,即由其他线程放弃锁时触发这个事件。
结束(Terminated):已终止线程的状态,即线程已经结束执行。
五种状态转换关系如下:
类结构