先明确一些概念
进程与线程
进程
进程是正在执行的计算机程序的实例,是计算机进行资源分配和调度的基本单位。进程可以由多个线程组成。
线程
线程是程序执行的最小单位,多个线程可以存在于同一个进程内,并发执行和共享系统资源,而不同进程不共享这些资源。
并行与并发
并行
指的是在多个处理器(或者多核)上同时处理多个任务
并发
指的是在一个处理器上同时处理多个任务
为什么要用线程池?
new thread()的弊端
- 线程的创建和销毁会带来一定的开销
- 缺乏统一管理,可能无限制的创建线程,相互之间的竞争可能占用系统过多资源
- 缺乏更多功能,比如定时执行,定期执行,线程中断
线程池的好处
- 可重复利用已创建好的线程,减少对象频繁创建销毁带来的性能开销
- 可有效控制线程的最大并放弃啊数,提高系统资源的使用率,通知避免资源过度竞争,避免堵塞
- 提供定时执行,定期执行,单线程,并发数控制等功能
java中的线程池
几个重要的类
接口Executor
void execute(Runnable command);
接口ExecutorService继承Executor,并扩展了一些方法
抽象类AbstractExecutorService实现了ExecutorService的部分方法
具体实现类ThreadPoolExecutor
Android中的线程池都是直接或间接通过配置ThreadPoolExecutor 来实现不同特性的线程池
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
- int corePoolSize,
核心线程数,除非allowCoreThreadTimeOut被设置为true,否则它闲着也不会死
- int maximumPoolSize,
最大线程数,活动线程数量超过它,后续任务就会排队
- long keepAliveTime,
超时时长,作用于非核心线程(allowCoreThreadTimeOut被设置为true时也会同时作用于核心线程),闲置超时便被回收
- TimeUnit unit,
枚举类型,设置keepAliveTime的单位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等
- BlockingQueue<Runnable> workQueue,
缓冲任务队列,线程池的execute方法会将Runnable对象存储起来
- ThreadFactory threadFactory)
线程工厂接口,只有一个new Thread(Runnable r)方法,可为线程池创建新线程
Executors这个类已经提供了常用的四种线程池创建
1. newFixedThreadPool
2. newCachedThreadPool
3. newScheduledThreadPool
4. newSingleThreadExecutor
newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。可以通过Runtime.getRuntime().availableProcessors()查看。
创建一个在共享的无界队列中使用固定数量的线程运行的线程池。在任何时候,有最多n个线程将处理任务。
如果所有线程都处于活动状态时,提交额外的任务,他们会在队列中等待,直到有一个线程可用。
如果在执行过程中出现故障,任何线程都会终止。如果需要执行后续任务,新的任务将取代它的位置。线程池中的线程会一直存在,直到它显式为止(调用shutdown)
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
final int finalI = i;
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("newFixedThreadPool: " + Thread.currentThread() + " "+ finalI);
}
});
}
打印结果:
newFixedThreadPool: Thread[pool-1-thread-1,5,main] 0
newFixedThreadPool: Thread[pool-1-thread-2,5,main] 1
newFixedThreadPool: Thread[pool-1-thread-3,5,main] 2
newFixedThreadPool: Thread[pool-1-thread-1,5,main] 3
newFixedThreadPool: Thread[pool-1-thread-2,5,main] 4
newFixedThreadPool: Thread[pool-1-thread-3,5,main] 5
newFixedThreadPool: Thread[pool-1-thread-1,5,main] 6
newFixedThreadPool: Thread[pool-1-thread-2,5,main] 7
newFixedThreadPool: Thread[pool-1-thread-3,5,main] 8
newFixedThreadPool: Thread[pool-1-thread-1,5,main] 9
newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int finalI = i;
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("testCacheThreadPool: " + Thread.currentThread() + " "+ finalI);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
打印结果:
testCacheThreadPool: Thread[pool-1-thread-1,5,main] 0
testCacheThreadPool: Thread[pool-1-thread-5,5,main] 4
testCacheThreadPool: Thread[pool-1-thread-3,5,main] 2
testCacheThreadPool: Thread[pool-1-thread-4,5,main] 3
testCacheThreadPool: Thread[pool-1-thread-2,5,main] 1
testCacheThreadPool: Thread[pool-1-thread-7,5,main] 6
testCacheThreadPool: Thread[pool-1-thread-6,5,main] 5
testCacheThreadPool: Thread[pool-1-thread-8,5,main] 7
testCacheThreadPool: Thread[pool-1-thread-9,5,main] 8
testCacheThreadPool: Thread[pool-1-thread-10,5,main] 9
这里并没有复用
newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
for (int i = 0; i < 10; i++) {
final int finalI = i;
newScheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("newScheduledThreadPool: " + Thread.currentThread() + " "+ finalI);
}
},2, TimeUnit.SECONDS);
}
打印结果:
newScheduledThreadPool: Thread[pool-1-thread-1,5,main] 0
newScheduledThreadPool: Thread[pool-1-thread-2,5,main] 2
newScheduledThreadPool: Thread[pool-1-thread-3,5,main] 1
newScheduledThreadPool: Thread[pool-1-thread-2,5,main] 4
newScheduledThreadPool: Thread[pool-1-thread-1,5,main] 3
newScheduledThreadPool: Thread[pool-1-thread-2,5,main] 6
newScheduledThreadPool: Thread[pool-1-thread-1,5,main] 7
newScheduledThreadPool: Thread[pool-1-thread-3,5,main] 5
newScheduledThreadPool: Thread[pool-1-thread-1,5,main] 9
newScheduledThreadPool: Thread[pool-1-thread-2,5,main] 8
newSingleThreadExecutor
创建一个在无界队列使用单个工作线程运行的执行器。但是要注意,如果这个单线程在shutdown之前因为故障导致线程终止,则在需要执行后续任务的时候将创建一个新的线程取代它。任务是被确保按顺序执行的,任意时刻只会激活一个任务。与newFixedThreadPool(1)不同的是,返回的执行器
ExecutorService newSingledThreadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
final int finalI = i;
newSingledThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("newSingledThreadPool: " + Thread.currentThread() + " "+ finalI);
}
});
}
打印结果:
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 0
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 1
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 2
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 3
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 4
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 5
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 6
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 7
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 8
newSingledThreadPool: Thread[pool-1-thread-1,5,main] 9
这里都是用的同一个线程
网友评论