在生产环境中,为每个任务分配一个线程存在一些缺陷:
1、线程生命周期的开销非常高:线程的创建和销毁是需要开销的
2、资源消耗:大量的空闲线程会占用许多内存
3、稳定性:在每个平台中线程的创建数量存在一个限制,如果超过,很可能会抛出一些异常
因此,java中引入了线程池Executor。
线程池,是指管理一组工作线程和一个工作队列的资源池。在创建一个线程池时,可以指定线程池中可以存在的工作线程的数量(开始时工作线程是还没创建的,当有任务时才会创建工作线程),当执行execute()方法时,会先将任务放进工作队列中,如果这时线程池中存在的工作线程数量小于线程池创建时指定的数量,则会创建一个工作线程(无论现在有没有工作线程是空闲的,只要是工作线程存在的数量小于指定的,就会创建),然后所有的工作线程就会反复的从工作队列中取出任务并执行它们。
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class Execution {
private static final Executor exec = Executors.newFixedThreadPool(5);
public static void main(String[] args) {
for(int i = 0; i < 15; i++){
TestThread task = new TestThread(i);
exec.execute(task);
}
}
}
class TestThread implements Runnable{
private int i;
public TestThread(int i){
this.i = i;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
输出结果:
pool-1-thread-3:2
pool-1-thread-4:3
pool-1-thread-3:5
pool-1-thread-4:6
pool-1-thread-4:8
pool-1-thread-4:9
pool-1-thread-4:10
pool-1-thread-4:11
pool-1-thread-4:12
pool-1-thread-4:13
pool-1-thread-4:14
pool-1-thread-5:4
pool-1-thread-1:0
pool-1-thread-2:1
pool-1-thread-3:7
下面是不同的线程池的创建方法:
在上面的例子中,我们会发现该程序一直处于运行状态,没法停止,这是因为Executor创建的线程只有全部停止,jvm才会退出,但是Executor创建的线程如果不关闭是不会停止的。因此,Executor有个ExecutorService子类,该类有用于管理线程生命周期的方法。
void shutdown(); 将平缓的关闭线程:不再接受新的任务,同时等待已经提交的任务执行完成
List<Runnable> shutdownNow();暴力关闭线程,不管有没完成的
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Execution {
private static final ExecutorService exec = Executors.newFixedThreadPool(5);
public static void main(String[] args) {
for(int i = 0; i < 15; i++){
TestThread task = new TestThread(i);
exec.execute(task);
}
exec.shutdown();
}
}
class TestThread implements Runnable{
private int i;
public TestThread(int i){
this.i = i;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
下面的例子,当所有任务执行完成后,jvm虚拟机就会停止运行。