线程池
线程池:使用池化思想管理线程的工具,主要解决资源分配的问题。
作用:(接受很多小任务并分发处理)很多小任务让一组线程来执行,而不是来一个任务就用一个线程。
内部维护若干线程。无任务时,这些任务都等待,有任务来到时,可以分配一个空闲线程来执行。如果所有的线程都忙碌,则放入等待队列或者增加一个新线程来处理。
Runnable, callable区别
Runnable :不会返回结果或抛出检查异常。不需要结果返回或者抛出异常检查的用Runnable
Callable:可以返回结果或抛出检查异常
Execute, submit()
Execute()提交不需要返回的任务。无法判断任务是否被线程池执行成功与否
Submit()会返回一个Future类型的对象。通过Future对象判断任务是否成功执行。且Future的get方法会获取返回值。get()会阻塞当前线程直到任务完成。get内部可以设置超时时间。
创造方法:
使用ThreadPoolExecutor的构造函数,自定义参数来创建线程池。
ThreadPoolExcuter executer = new ThreadPoolExecuter(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(QUEUE_CAPACITY),
new ThreadPoolExecuter.CallerRunsPolicy());
ThreadPoolExcuter important parametors:
1. corePoolSize:最多可以同时运行的线程数目
2. maximumPoolSize:线程池最大接受任务数目。 >这个值,说明不仅线程池内阻塞队列满了,还需要根据拒绝策略来处理该任务。默认的处理方法是直接抛异常。如果<这个值,且阻塞队列满了,则需要添加工程线程并执行。
3. workQueue (BlockingQueue<Runnable>): 新任务来的时候判断当前运行线程数目量是否>corePoolSize并且<maximumPoolSize。满足就放到这个对列里。
其他参数:
1.keepAliveTime: 线程最大等待时间,超时了就被销毁
2.handler:饱和策略: >maximumPoolSize, 默认会抛出异常
线程的构建方法
实例化一个Thread实例,然后调用它的start()方法:
方法1. 从Thread派生一个自定义类,然后覆写run()方法:
Thread t = new MyThread();
t.start();
class MyThread extends Thread {
@Override
public void run() {
}
}
方法2. 创建Thread实例时,传入一个Runnable实例:
Thread t = new Thread(new MyRunnable());
...
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("start new thread!");
}
}
线程池的构建方法
JDK提供了ExecutorService实现了线程池功能;Executors提供了静态方法创建不同类型的ExecutorService;必须调用shutdown()关闭ExecutorService;ScheduledThreadPool可以定期调度多个任务
ExecutorService只是接口,Java标准库提供的几个常用实现类有:
FixedThreadPool
:线程数固定的线程池;
CachedThreadPool
:线程数根据任务动态调整的线程池;
SingleThreadExecutor
:仅单线程执行的线程池。
创建这些线程池的方法都被封装到Executors这个类中。
ScheduledThreadPool
: 里面的线程可以定期反复执行。
// ScheduledThreadPool的方法
ScheduledExecutorService ses = Executors.newScheduledThreadPool(4);
// FixedRate固定时间间隔
ses.scheduleAtFixedRate(new Task("fixed-rate"), 2, 3, TimeUnit.SECONDS);
// FixedDelay上一次任务执行完毕后,等待固定的时间间隔
// 2秒后开始执行定时任务,以3秒为间隔执行:
ses.scheduleWithFixedDelay(new Task("fixed-delay"), 2, 3, TimeUnit.SECONDS);
// fixed举例
import java.util.concurrent.*;
public static void main(){
// 这一步很重要
ExecutorService es = Executors.newFixedThreadPool(4);
for (int i = 0; i < 6; i++) {
es.submit(new Task("" + i));
}
// 关闭线程池:
es.shutdown();
}
public Task implements Runnable{
private final String name;
public Thread(String name){
this.name = name;
}
public void run(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
关闭
shutdown()
方法关闭线程池的时候,它会等待正在执行的任务先完成,然后再关闭。shutdownNow()
会立刻停止正在执行的任务,awaitTermination()
则会等待指定的时间让线程池关闭。