把若干用户线程添加到线程池中,由线程池来管理线程
为什么要使用线程池:
- 减少了创建和销毁线程的次数,每个工作线程都可以被重复使用或利用,可以并发执行多个任务
- 可以根据系统的承受能力,调整线程池中的工作线程数目,防止因为消耗过多的内存,而使服务器宕机(down)
结论:java给提供了一些api方法,用于更好地管理线程,让程序员专心写线程的逻辑
先创建一个MyThread类个MyThread2类,供后面例子使用
public class MyThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyThread2 extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行2");
}
}
手动创建线程池
ThreadpoolExecutor xxx = new ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
参数 | 含义 | |
---|---|---|
int corePoolSize | 核心线程数量 | |
int maximumPoolSize | 最大线程数量 | |
long keepAliveTime | 空闲的线程存活时间 | |
TimeUnit unit | 时间单位 | |
BlockingQueue |
阻塞队列 | |
RejectedExecutionHandler handler | 拒绝服务助手 |
例子
/**
* 手动创建线程池
*/
public class TestExecutorsService {
/**
* 手动创建了一个线程池
* @param args
*/
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 30L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("线程数超过了线程池的容量,拒接执行任务-->"+r);
}
});
//把线程放在线程池中并执行
threadPoolExecutor.execute(new TestThread(1));
threadPoolExecutor.execute(new TestThread(2));
threadPoolExecutor.execute(new TestThread(3));
threadPoolExecutor.execute(new TestThread(4));
threadPoolExecutor.execute(new TestThread(5));
threadPoolExecutor.execute(new TestThread(6));
threadPoolExecutor.execute(new TestThread(7));
threadPoolExecutor.execute(new TestThread(8));
threadPoolExecutor.execute(new TestThread(9));
threadPoolExecutor.execute(new TestThread(10));
threadPoolExecutor.execute(new TestThread(11));
threadPoolExecutor.execute(new TestThread(12));
threadPoolExecutor.execute(new TestThread(13));
threadPoolExecutor.execute(new TestThread(14));
threadPoolExecutor.execute(new TestThread(15));
threadPoolExecutor.execute(new TestThread(16));
threadPoolExecutor.execute(new TestThread(17));
}
}
/**
* 写线程的逻辑
*/
class TestThread implements Runnable{
private int num;
public TestThread(int num){
this.num = num;
}
@Override
public void run() {
System.out.println("第"+num+"号线程开始执行");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第"+num+"号线程执行结束");
}
}
线程池api的使用
Executors的线程工具类,此类提供了若干静态方法,这些静态方法用于生成线程池对象
Executors.newSingleThreadExecutor();
创建一个单线程的线程池,这个线程池只有一个线程在工作 即单线程执行任务,如果这个唯一的线程因为异常结束,那么就会有一个新的线程来替代它,因此,线程池保证所有的任务是按照任务的提交顺序来执行
例子
会逐个执行,每次只有一个线程在工作
public class TestExecutors_SingleThreadExcetor {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
//创建若干线程
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
MyThread mt4 = new MyThread();
MyThread mt5 = new MyThread();
//把线程提交给线程池
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
//关闭线程池
pool.shutdown();
}
}
Executors.newFilexedThreadPool(int nThreads);
创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小,线程池的大小一旦达到最大,就会保持不变;如果某个线程因为执行异常而结束,线程就会补充一个新的线程
###例子 下面例子两个线程2个线程运行,因为参数给的是2
public class TestExecutors_FixedThreadExcetor {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建若干线程
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
MyThread2 mt4 = new MyThread2();
MyThread2 mt5 = new MyThread2();
//把线程提交给线程池
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
//关闭线程池
pool.shutdown();
}
}
Executors.newCacheedThreadPool();
创建一个可以缓冲的线程池,如果线程池大小超过处理的任务所需要的线程,那么就会回收部分线程,当任务数目增加的时候,此线程池又可以智能的添加新的线程来处理任务,此线程池不会对线程大小做限制,线程池的大小完全依赖操作系统能够创建的最大的大小
例子
public class TestExecutors_CachedThreadExcetor {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
//创建若干线程
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
MyThread mt4 = new MyThread();
MyThread mt5 = new MyThread();
//把线程提交给线程池
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
//关闭线程池
pool.shutdown();
}
}
Executors.newScheduledThreadPool(int corePoolSize);
创建一个大小无限制的线程池,此线程池支持定时及周期性的执行任务的需求
例子
public class TestExecutors_ScheduledThreadExcetor {
public static void main(String[] args) {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
pool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("计划执行run");
}
},2000,500, TimeUnit.MILLISECONDS);
}
}