线程池:
因为线程缺乏统一管理,占用过多系统资源,缺乏更多功能,如定时执行、定期执行等
好处: 重用存在的线程,减少对象创建,消亡的开销。
有效控制最大并发数,提高系统资源使用率
定时执行、定期执行
线程池所在包java.util.concurrent
顶级接口是Executor,真正的线程池接口是ExecutorService
java,util.Executors类提供创建线程池的方法
这些全是Executors的构造方法
newCachedThreadPool() 创建一个可缓存的线程池,有任务时才创建任务
newSingleThreadExecutor() 创建一个单线程池
newFixedThreadPool(int nThreads) 创建一个固定长度的线程池,空闲线程会一直保留,参数nThreads设定线程池中线程的数目
newScheduledThreadPool(int corePoolSize ) 创建了一个固定的线程池,而且以延迟或定时的方式来执行任务,参数是最大的线程数,而且这个对应的是ScheduledExecutorService这个类去接收
案例1:这个案例可以使用前三个构造方法newCachedThreadPool()、newSingleThreadExecutor()、newFixedThreadPool(int nThreads)
package cn.lnm.exp2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyThreadDemo {
/**
* @param args
*/
public static void main(String[] args) {
ExecutorService es=Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
es.execute(new MineThread(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MineThread implements Runnable{
int num;
public MineThread(int num) {
super();
this.num = num;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+num);
}
}
案例2:这个案例对应的是ScheduledExecutorService这个类去接收
package cn.lnm.exp2;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MyThreadDemo {
/**
* @param args
*/
public static void main(String[] args) {
ScheduledExecutorService es = Executors.newScheduledThreadPool(3);// 里面的参数是最大的线程数
System.out.println("**************");
es.scheduleAtFixedRate(new MineThread(), 1, 2, TimeUnit.SECONDS);
}
}
class MineThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"延时1秒执行,每2秒执行一次");
}
}
ThreadPoolExecutor:创建一个自定义线程池
构造器中各个参数的含义:
corePoolSize 核心池的大小
maximumPoolSize 线程池最大线程数
keepAliveTime 表示线程没有任务执行时最多保持多篇时间会终止
unit 参数keepAliveTime的时间单位,使用TimeUnit这个枚举去设置是秒否是毫秒
workQueue 一个阻塞队列,用来存储等待执行的任务的大小(就像去医院排队看病,可以在外面等待的病人总人数)
threadFactory 线程工厂,主要用来创建线程
handler 表示当拒绝处理任务的策略
案例3:这个代码执行到第12条信息的时候,会报错,因为这个线程池的大小,一个是执行的线程池5,一个是最大可以有7条线程池,然后可以排队的线程池是4,一共可以有11条线程,然后第12条的时候,处理不了,直接拒绝了这条线程,所以会报异常
package cn.lnm.exp2;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit;
public class MyThreadDemo {
/**
* @param args
*/
public static void main(String[] args) {
//创建一个自定义线程池
ThreadPoolExecutor tpe=new ThreadPoolExecutor(5, 7, 300, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(4));
for (int i = 1; i <= 12; i++) {
tpe.execute(new MineThread(i));
System.out.println("线程池中线程数:"+tpe.getPoolSize()+",队列中等待执行的任务数"+tpe.getQueue().size()+",已经执行完的任务数"+tpe.getCompletedTaskCount());
}
tpe.shutdown();//关闭线程池
}
}
class MineThread implements Runnable {
int num;
public MineThread(int num) {
super();
this.num = num;
}
@Override
public void run() {
System.out.println("正在执行任务"+num);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务"+num+"执行完毕");
}
}