一:线程池
在进行多线程开发时,频繁地创建销毁线程需要一定的时间,这样非常影响系统的效率,而线程池提供了一种非常便捷的方式:在执行完任务的时候线程池中的线程不必销毁,在线程池中处于等待状态,当有新的任务到达时,再去执行新的任务。
所以,线程池中存储的是任务,这些任务在内存中存放于队列中。
1、线程池分类:
- ForkJoinPool,
- ScheduledThreadPoolExecutor ,
(以上这俩种不常用,这里不介绍了) - ThreadPoolExecutor : 在ThreadPoolExecutor中定义了一个volatile变量,另外定义了几个static final变量表示线程池的各个状态:
private static final int RUNNING = -1 << COUNT_BITS;//接受新任务并且能处理已经进入阻塞队列的任务
private static final int SHUTDOWN = 0 << COUNT_BITS;// 不接受新任务,但是处理已经进入阻塞队列的任务(shutdown())
private static final int STOP = 1 << COUNT_BITS;//不接受新任务,不处理已经进入阻塞队列的任务并且中断正在运行的任务(shutdownNow())
private static final int TIDYING = 2 << COUNT_BITS;//所有的任务都已经终止,线程池内任务为0,阻塞队列也没有任务, 线程转化为TIDYING状态并且调用terminated钩子函数
private static final int TERMINATED = 3 << COUNT_BITS;//terminated钩子函数已经运行完成
2、创建线程
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂和拒绝执行处理程序。
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂。
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
创建一个新的 ThreadPoolExecutor与给定的初始参数和默认拒绝执行处理程序。
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
创建一个新 ThreadPoolExecutor给定的初始参数。
参数说明:
corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于核心时,这是多余的空闲线程在终止之前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位
workQueue - 在执行任务之前用于保存任务的队列。 该队列将仅保存execute方法提交的Runnable任务。
threadFactory - 执行程序创建新线程时使用的工厂
handler - 执行被阻止时使用的处理程序,因为达到线程限制和队列容量
平常,我们使用线程工具类Executors来创造线程
举例:
ExecutorService p1=Executors.newCachedThreadPool();//短任务线程池
ExecutorService p2=Executors.newFixedThreadPool(5);//规定数量的线程池
ExecutorService p3=Executors.newSingleThreadExecutor();//单一
3、线程的启动
submit()与execute()都是执行任务,但是submit可以有返回值
举例:
for(int i=0;i<100;i++) {
p2.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int rand=(int)(Math.random()*100);
System.out.println(Thread.currentThread().getId()+"--"+rand);
}
});
}
for(int i=0;i<100;i++) {
p2.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
System.out.println("睡了俩秒");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int rand=(int)(Math.random()*100);
System.out.println(Thread.currentThread().getId()+"--"+rand);
}
});
}
4、BlockingQueue workQueue) //阻塞队列
创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂和拒绝执行处理程序。
BlockingQueue不接受null元素。实现设计主要用于生产者 - 消费者队列,线程安全的
BlockingQueue的方法:
//将指定的元素插入到此队列中,如果可以立即执行此操作,而不会违反容量限制, true在成功时返回,如果当前没有可用空间,则返回false。
boolean offer(E e)
//将指定的元素插入到此队列中,等待空间可用---------------------------阻塞等待
put(E e)
// 检索并删除此队列的头,如有必要,等待元素可用
E take()
BlockingQueue的成员
LinkedBlockingQueue(int capacity) 队列有空间大小----底层是链表
Class ArrayBlockingQueue 底层是静态数组