对于线程池的理解
- 简单理解就好,就一个池子
- 池子里面放着线程,需要的时候向池子要,用完归还回去
- 由于是资源重复利用,所以有助于提高系统性能,节约系统资源,是个好孩子
- 问题在于池子的管理,例如 线程不够用的时候怎么扩容?装得下吗?别人来要线程,要等多久?怎么控制线程的动向?别人一次要多个线程怎么办?空闲的线程怎么管理?其实如果单单使用的话就不用我们管了,java.util.concurrent 包下已经有大神帮我们写好
线程池主要(ExecutorService)的 api
名称 | 说明 |
---|---|
shutdown() | 一个一个地关闭正在运行的线程,但是对后来才启动的线程无效 |
shutdownNow() | 立刻强行停止所有线程,包括正在等待的, |
isShutdown() | 调用 isShutdown(),会返回 true,否则false |
isTerminated() | 如果当前线程池被关闭(例如其他地方有调用 isShutdown() ),会返回 true,否则false |
isShutdown() | 如果当前线程池被关闭,会返回 true,否则false |
awaitTermination(long timeout, TimeUnit unit) | 这限定时间内等待所有线程任务完成后关闭线程池,和 shutdown() 差不多,都是等待所有任务完成,但是多了一个等待时间 |
submit(Callable task) | 会返回 Future,用于实现一个函数回调,对于想要开启一个线程后获取返回值的话,有很大帮助 |
submit(Callable task) | 会返回 Future,用于实现一个函数回调,对于想要开启一个线程后获取返回值的话,有很大帮助 |
invokeAll(Collection<? extends Callable> tasks) | 会返回 List<Future>,和上面的 submit(Callable task) 类似,不过传入的是列表,等待所有任务完成后一齐返回,用于批量操作 |
invokeAny(Collection<? extends Callable> tasks) | 会返回 T,和上面的 invokeAll(Collection<? extends Callable> tasks) 类似,不过有其中一个任务先完成,立刻返回 |
Java 中四种线程池:缓存线程池、定容线程池、周期线程池、单线程化线程池
下面是简单使用例子
public class TestThreadPool {
static class TestThread implements Runnable {
private String threadName;
public TestThread(String threadName) {
this.threadName = threadName;
}
@Override
public void run() {
System.out.println(threadName + " 进来了, 当前线程:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println(" (============测试 缓存线程池 CachedThreadPool============)");
// 创建一个缓存线程池,如果线程不够,会自动创建,太多了,过了线程的存活期会自动销毁线程,理论上可以容纳无限的线程,只要内存空间足够
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.submit(new TestThread("线程任务对象 0 "));
cachedThreadPool.submit(new TestThread("线程任务对象 1 "));
cachedThreadPool.submit(new TestThread("线程任务对象 2 "));
cachedThreadPool.shutdown();
System.out.println("\n ============测试 定容线程池 FixedThreadPool============");
// 创建一个固定容量的线程池,类似 Semaphore,可以控制线程数量,多出的线程会在内部的一个队列中等待有空闲的线程
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
fixedThreadPool.submit(new TestThread("线程任务对象 3 "));
fixedThreadPool.submit(new TestThread("线程任务对象 4 "));
fixedThreadPool.submit(new TestThread("线程任务对象 5 "));
fixedThreadPool.submit(new TestThread("线程任务对象 6 "));
fixedThreadPool.shutdown();
System.out.println("\n ============测试 周期线程池 ScheduledThreadPool============");
// 创建一个按周期活动/延时启动的线程池, 可以当作定时器使用,
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(new TestThread("线程任务对象 7 "), 1, TimeUnit.SECONDS);
scheduledThreadPool.schedule(new TestThread("线程任务对象 8 "), 2, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(new TestThread("线程任务对象 9 "), 0, 1, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(new TestThread("线程任务对象 10 "), 0, 2, TimeUnit.SECONDS);
Thread.sleep(5000);
scheduledThreadPool.shutdown();
System.out.println("\n ============测试 单线程化线程池 SingleThreadExecutor============");
// 创建 单线程化线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.submit(new TestThread("线程任务对象 11 "));
singleThreadExecutor.submit(new TestThread("线程任务对象 12 "));
singleThreadExecutor.submit(new TestThread("线程任务对象 13 "));
singleThreadExecutor.shutdown();
}
}
输出结果
============测试 缓存线程池 CachedThreadPool============
线程任务对象 0 进来了, 当前线程:pool-1-thread-1
============测试 定容线程池 FixedThreadPool============
线程任务对象 2 进来了, 当前线程:pool-1-thread-3
线程任务对象 1 进来了, 当前线程:pool-1-thread-2
线程任务对象 3 进来了, 当前线程:pool-2-thread-1
线程任务对象 4 进来了, 当前线程:pool-2-thread-2
============测试 周期线程池 ScheduledThreadPool============
线程任务对象 5 进来了, 当前线程:pool-2-thread-3
线程任务对象 9 进来了, 当前线程:pool-3-thread-1
线程任务对象 10 进来了, 当前线程:pool-3-thread-2
线程任务对象 6 进来了, 当前线程:pool-2-thread-1
线程任务对象 7 进来了, 当前线程:pool-3-thread-1
线程任务对象 9 进来了, 当前线程:pool-3-thread-2
线程任务对象 8 进来了, 当前线程:pool-3-thread-3
线程任务对象 9 进来了, 当前线程:pool-3-thread-2
线程任务对象 10 进来了, 当前线程:pool-3-thread-1
线程任务对象 9 进来了, 当前线程:pool-3-thread-3
线程任务对象 10 进来了, 当前线程:pool-3-thread-2
线程任务对象 9 进来了, 当前线程:pool-3-thread-3
============测试 单线程化线程池 SingleThreadExecutor============
线程任务对象 11 进来了, 当前线程:pool-4-thread-1
线程任务对象 12 进来了, 当前线程:pool-4-thread-1
线程任务对象 13 进来了, 当前线程:pool-4-thread-1
补充一些(ScheduledExecutorService)的 api
名称 | 说明 |
---|---|
schedule(Runnable command, long delay, TimeUnit unit) | 传入 Runnable 实例,delay 为推后多长时间启动 |
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) | 传入 Runnable 实例,initialDelay 为推后多长时间启动,period 为定时运行的周期,TimeUnit 为时间格式 |