概念
线程的创建与销毁都需要销毁资源,为了避免频繁的创建与销毁线程,可以让创建的线程进行复用。类似数据库连接池的概念,
Java中的线程池
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
缓存线程池(CachedThreadPool )
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getId() + " : " + index);
}
});
}
cachedThreadPool.shutdown();
}
}
打印结果发现 执行上一个线程处理的过来打印,所以都是同一个线程完成任务.
9 : 0
9 : 1
9 : 2
9 : 3
9 : 4
9 : 5
9 : 6
9 : 7
9 : 8
9 : 9
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getId() + " : " + index);
}
});
}
cachedThreadPool.shutdown();
}
}
打印结果,发现当前线程池的线程处理不过来,自动创建新的线程来做处理
9 : 0
12 : 3
10 : 1
11 : 2
14 : 5
15 : 6
13 : 4
16 : 7
14 : 8
16 : 9
定长线程池(FixedThreadPool)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
public void run() {
try {
System.out.println(Thread.currentThread().getId() + " : " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
fixedThreadPool.shutdown();
}
}
打印结果 始终只有三个线程处理,没有来得及处理的排队等待
9 : 0
10 : 1
11 : 2
10 : 3
11 : 5
9 : 4
11 : 6
9 : 8
10 : 7
10 : 9
调度计划线程池(ScheduledThreadPool)
三秒钟之后开始执行,执行完毕就关闭,不循环
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
//三秒后执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.shutdown();
}
}
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getId() + " : delay 3 seconds, and excute every 2 seconds");
}
}, 3, 2, TimeUnit.SECONDS);
}
}
打印结果: 三秒后开始执行打印,之后没两秒执行一次,不断轮询,每次执行的线程不固定
9 : delay 3 seconds, and excute every 2 seconds
9 : delay 3 seconds, and excute every 2 seconds
11 : delay 3 seconds, and excute every 2 seconds
9 : delay 3 seconds, and excute every 2 seconds
12 : delay 3 seconds, and excute every 2 seconds
11 : delay 3 seconds, and excute every 2 seconds
13 : delay 3 seconds, and excute every 2 seconds
9 : delay 3 seconds, and excute every 2 seconds
单线程线程池(SingleThreadExecutor)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 20; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
public void run() {
try {
System.out.println(Thread.currentThread().getId() + " : " + index);
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
打印结果: 发现每次都是同一个线程执行
9 : 0
9 : 1
9 : 2
9 : 3
9 : 4
9 : 5
9 : 6
9 : 7
9 : 8
9 : 9
9 : 10
9 : 11
9 : 12
9 : 13
9 : 14
9 : 15
9 : 16
9 : 17
9 : 18
9 : 19
自定义线程池(ThreadPoolExecutor)
说明
上面四种线程池除了(ScheduledThreadPool)外都继承与ThreadPoolExecutor类,只不过传递的参数不同而已.
ThreadPoolExecutor的构造函数如下
corePoolSize:指定线程池中线程数量
maximumPoolSize : 指定线程池中最大线程数
keepAliveTime : 当线程池线程数量超过corePoolSize时,多余的空闲线程存活时间.
unit : keepAliveTime 参数的单位
workQueue : 任务队列,被加入进来执行的任务,但是未被执行的任务队列
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
自定义线程池
上面既然发现jdk提供的线程池来自于ThreadPoolExecutor,
那么一样可以自定义
ExecutorService singleThreadExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.DAYS,
new LinkedBlockingQueue<Runnable>(),new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
return t;
}
});
扩展线程池
执行之前,结束之后,终止调用的方法.
ExecutorService es = new ThreadPoolExecutor(10, 10, 0, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>()){
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
}
@Override
protected void terminated() {
super.terminated();
}
};