Java 线程 -- 线程池
-
线程池就是
存放线程的容器,容器里存放了很多可以复用的线程。 -
创建线程(new Thread())和销毁线程的花销是比较大的,比较消耗资源,创建和消耗线程的时间有可能比处理业务的时间还要长。
使用线程池的好处
-
提高效率:需要使用线程时,直接从线程池中取一个,效率高于创建一个线程。 -
减少系统资源的浪费:每一个工作线程都可以被重复利用,执行多个任务,减少了线程的创建与销毁。 -
提高系统响应速度:不需要创建和销毁线程,相应的时间也就不需要,只计算任务时间即可。
线程池的创建
Executor 接口
-
Executor是线程池的顶层接口,将任务的提交与任务的执行分离开来,只有一个void execute(Runnable);方法。 -
ExecutorService 接口继承并扩展了 Executor 接口,提供了 Runnable、Callable、FutureTask 等主要线程实现接口扩展方法,新增了许多 shutdown()、submit() 等线程控制方法。 -
AbstractExecutorService 类实现了 ExecutorService 接口,只是新增了一些创建新任务的方法,如:newTaskFor()。 -
ScheduledExecutorService 接口继承 ExecutorService 接口,并定义了延迟或定期执行的周期性方法。 -
ThreadPoolExecutor 类继承 AbstractExecutorService 类,是线程池的核心实现类,用来执行被提交的任务。 -
ScheduledThreadPoolExecutor继承 ThreadPoolExecutor 类并实现了 ScheduledExecutorService 接口,是延时执行类任务的主要实现类。
ThreadPoolExecutor 类
-
作为
线程池的核心实现类,用来执行被提交的任务。 -
所有的线程池
都是要通过 ThreadPoolExecutor 类来构造的。
七个核心参数
-
corePoolSize(int):核心线程池的大小。
-
maximumPoolSize(int):最大线程池的大小。
-
keepAliveTime(long):非核心线程的存活时间。
-
unit(TimeUnit):keepAliveTime 的时间单位。
-
workQueue(BlockingQueue<>):用来暂时保存任务的工作队列。
-
threadFactory(ThreadFactory):线程工厂提供线程的创建方式,默认使用 Executors.defaultThreadFactory() 创建的工厂。
-
handler(RejectedExecutionHandler):当线程池所处理的任务数超过其承载容量或关闭后继续有任务提交时,所调用的拒绝策略。
线程状态
private static final int RUNNING=-1<<COUNT_BITS;
private static final int SHUTDOWN=0<<COUNT_BITS;
private static final int STOP=1<<COUNT_BITS;
private static final int TIDYING=2<<COUNT_BITS;
private static final int TERMINATED=3<<COUNT_BITS;
创建线程池
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* ThreadPoolExecutor
*/
public static void main(String[] args) {
// 创建线程工厂
TestThreadPollFactory factory = new TestThreadPollFactory("线程工厂 测试,");
// 创建 先进先出 队列
ArrayBlockingQueue<Runnable> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
// 创建 先进先出 队列
LinkedBlockingQueue<Runnable> linkedBlockingQueue = new LinkedBlockingQueue<>(3);
// 创建 特殊 队列
SynchronousQueue<Runnable> synchronousQueue = new SynchronousQueue<Runnable>(true);
// 创建线程池(核心线程数、最大线程数、线程空闲时间、线程空闲时间的单位、队列)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 3, 10, TimeUnit.SECONDS, arrayBlockingQueue);
for(int i = 0; i < 3; i++) {
threadPoolExecutor.submit(RUNNABLE);
}
// 创建线程池(核心线程数、最大线程数、线程空闲时间、线程空闲时间的单位、队列、线程工厂)
ThreadPoolExecutor threadPoolExecutor1 = new ThreadPoolExecutor(1, 3, 10, TimeUnit.SECONDS, linkedBlockingQueue, factory);
for(int i = 0; i < 3; i++) {
threadPoolExecutor1.submit(RUNNABLE);
}
// 创建线程池(核心线程数、最大线程数、线程空闲时间、线程空闲时间的单位、队列、线程工厂、拒绝策略)
ThreadPoolExecutor threadPoolExecutor2 = new ThreadPoolExecutor(1, 3, 10, TimeUnit.SECONDS, synchronousQueue, factory, new ThreadPoolExecutor.DiscardOldestPolicy());
for(int i = 0; i < 3; i++) {
threadPoolExecutor2.submit(RUNNABLE);
}
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
threadPoolExecutor.shutdown();
threadPoolExecutor1.shutdown();
threadPoolExecutor2.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
队列
-
ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小。- 创建例子:
ArrayBlockingQueue<Runnable> arrayBlockingQueue = new ArrayBlockingQueue<>(3);。
- 创建例子:
-
LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为 Integer.MAX_VALUE。- 创建例子:
LinkedBlockingQueue<Runnable> linkedBlockingQueue = new LinkedBlockingQueue<>(3);。
- 创建例子:
-
SynchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。- 创建例子:
SynchronousQueue<Runnable> synchronousQueue = new SynchronousQueue<Runnable>(true);。
- 创建例子:
Executors 类
-
Executors 类(并发包)提供了 6 种创建线程池方法。
- newCacheTreadPool、newFixedTreadPool、newScheduleTreadPool、newSingleTreadExecutor、 newWorkStealingPool、newSingleThreadScheduledExecutor。
-
这些方法最终都是
通过配置 ThreadPoolExecutor 的不同参数,来达到不同的线程管理效果。 -
Executors 类在
java.util.concurrent并发包下,虽然不推荐用这种方法创建线程池。
submit() 方法、execute() 方法 和 schedule() 方法
-
submit() 方法有返回值,便于异常处理。
执行任务(单次)。-
方法之一:
<T> Future<T> submit(Callable<T> task);,传入 Callable<> 线程类。 -
方法之一:
<T> Future<T> submit(Runnable task, T result);,传入 Runnable 线程类 和 返回值类。 -
方法之一:
Future<?> submit(Runnable task);,传入 Runnable 线程类。 -
方法 submit() 是在 ExecutorService 接口中声明的。
-
-
execute() 方法没有返回值。
执行任务(单次)。- 方法只有一种:
void execute(Runnable command);,在 Executor 接口定义。
- 方法只有一种:
-
schedule() 方法,是用来调用
周期性的、定时的、延迟的任务。-
方法 schedule() 是在 ScheduledExecutorService 接口中声明的。
-
方法之一:
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);,传入 Runnable 线程类、延迟时间及其单位。 -
方法之一:
ScheduledFuture<?> schedule(Callable<V> callable, long delay, TimeUnit unit);,传入 Callable 线程类、延迟时间及其单位。 -
方法基本上都是这种模式。
-
还有
scheduleAtFixedRate()、scheduleWithFixedDelay()。
-
newCacheTreadPool
-
创建一个
可缓存的无界线程池。 -
如果线程池长度超过处理需要,可灵活回收空线程;若无可回收,则新建线程。
-
当线程池中的
线程空闲时间超过 60 s,则会自动回收该线程。 -
当
任务超过线程池的线程数则创建新的线程。 -
线程池的
大小上限为 Integer.MAX_VALUE,可看作无限大。 -
创建方法:
Executors.newCachedThreadPool(ThreadFactory); 或 Executors.newCachedThreadPool();。
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* newCacheTreadPool
*/
public static void main(String[] args) {
// 创建线程工厂
TestThreadPollFactory factory = new TestThreadPollFactory("线程工厂 测试,");
// 创建线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool(factory);
for(int i = 0; i < 10; i++) {
cachedThreadPool.submit(RUNNABLE);
}
// 创建线程池
ExecutorService cachedThreadPool1 = Executors.newCachedThreadPool();
for(int i = 0; i < 9; i++) {
cachedThreadPool1.submit(RUNNABLE);
}
// 创建线程池
ExecutorService cachedThreadPool2 = Executors.newCachedThreadPool(factory);
for(int i = 0; i < 8; i++) {
cachedThreadPool2.submit(CALLABLE);
}
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
cachedThreadPool.shutdown();
cachedThreadPool1.shutdown();
cachedThreadPool2.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
- 线程池
通过 submit() 方法创建子线程 来执行任务。
newFixedTreadPool
-
创建一个
指定大小的线程池。 -
可控制线程的最大并发数,超出的线程会在 LinkedBlockingQueue 阻塞队列中等待。
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* newFixedTreadPool
*/
public static void main(String[] args) {
// 创建线程工厂
TestThreadPollFactory factory = new TestThreadPollFactory("线程工厂 测试,");
// 创建线程池(传入需要创建的线程数 n 和 线程工厂)
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5, factory);
for(int i = 0; i < 10; i++) {
fixedThreadPool.submit(RUNNABLE);
}
// 创建线程池(传入需要创建的线程数 n)
ExecutorService fixedThreadPool1 = Executors.newFixedThreadPool(5);
for(int i = 0; i < 9; i++) {
fixedThreadPool1.submit(RUNNABLE);
}
// 创建线程池(传入需要创建的线程数 n 和 线程工厂)
ExecutorService fixedThreadPool2 = Executors.newFixedThreadPool(5, factory);
for(int i = 0; i < 8; i++) {
fixedThreadPool2.submit(CALLABLE);
}
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
fixedThreadPool.shutdown();
fixedThreadPool1.shutdown();
fixedThreadPool2.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
- 线程池
通过 submit() 方法创建子线程 来执行任务。
newScheduleTreadPool
-
创建一个
定长的线程池。 -
可以
指定线程池核心线程数,支持定时及周期性任务的执行。
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* newScheduledThreadPool
*/
public static void main(String[] args) {
// 创建线程工厂
TestThreadPollFactory factory = new TestThreadPollFactory("定时任务、周期任务,测试,");
// 创建线程池(传入核心线程数 n 和 线程工厂)
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5, factory);
// 定时任务(执行一次的任务,延迟 1s 后执行)
scheduledExecutorService.schedule(RUNNABLE, 1, TimeUnit.SECONDS);
// 定时任务(执行一次的任务,延迟 1s 后执行),同样可以放入 Callable<> 类对象
scheduledExecutorService.schedule(CALLABLE, 1, TimeUnit.SECONDS);
// 定时任务(延迟 1s 后执行,每 3s 一次,按照固定的周期执行)
scheduledExecutorService.scheduleAtFixedRate(RUNNABLE, 1, 3, TimeUnit.SECONDS);
// 定时任务(延迟 1s 后执行,每 3s 一次,按照固定的延迟执行)
scheduledExecutorService.scheduleWithFixedDelay(RUNNABLE, 1, 3, TimeUnit.SECONDS);
// 创建线程池(传入核心线程数 n)
ScheduledExecutorService scheduledExecutorService1 = Executors.newScheduledThreadPool(5);
for(int i = 0; i < 9; i++) {
scheduledExecutorService1.submit(RUNNABLE);
}
// 创建线程工厂
TestThreadPollFactory factory1 = new TestThreadPollFactory("线程工厂 测试,");
// 创建线程池(传入需要创建的线程数 n 和 线程工厂)
ScheduledExecutorService scheduledExecutorService2 = Executors.newScheduledThreadPool(5, factory1);
for(int i = 0; i < 8; i++) {
scheduledExecutorService2.submit(CALLABLE);
}
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
scheduledExecutorService.shutdown();
scheduledExecutorService1.shutdown();
scheduledExecutorService2.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
-
线程池
通过 submit() 方法创建子线程 来执行任务。 -
同时,
通过 schedule()、scheduleAtFixedRate()、scheduleWithFixedDelay() 方法执行定时、周期任务。
newSingleTreadExecutor
-
创建一个
单线程化的线程池。也可以理解为:创建一个单线程执行器。 -
它
只有一个线程,用仅有的一个线程来执行任务,保证所有的任务按照指定顺序(FIFO,或 LIFO,或 优先级)执行。 -
所有的任务都
保存在队列 LinkedBlockingQueue 中,等待唯一的单线程来执行任务。
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* newSingleThreadExecutor
*/
public static void main(String[] args) {
// 创建线程工厂
TestThreadPollFactory factory = new TestThreadPollFactory("线程工厂 测试,");
// 创建线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(factory);
for(int i = 0; i < 3; i++) {
singleThreadExecutor.submit(RUNNABLE);
}
for(int i = 0; i < 3; i++) {
singleThreadExecutor.submit(CALLABLE);
}
// 创建线程池
ExecutorService singleThreadExecutor1 = Executors.newSingleThreadExecutor();
for(int i = 0; i < 3; i++) {
singleThreadExecutor1.submit(RUNNABLE);
}
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
singleThreadExecutor.shutdown();
singleThreadExecutor1.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
- 线程池
通过 submit() 方法创建子线程 来执行任务。
newWorkStealingPool
-
创建一个
并发的线程池。默认将 CPU 的数量作为传入参数。 -
能够合理的使用 CPU 进行对任务操作(并行操作)。
-
适合使用在很耗时的任务中。 -
底层用的 ForkJoinPool 来实现的。
-
ForkJoinPool 的优势在于:可以
充分利用多核 CPU 的优势,把一个任务拆分成多个小任务分发到不同的cpu核心上执行,执行完后再把结果收集到一起返回。
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* newWorkStealingPool
*/
public static void main(String[] args) {
// 创建线程池
ExecutorService executorService = Executors.newWorkStealingPool();
for(int i = 0; i < 3; i++) {
executorService.execute(RUNNABLE);
}
ExecutorService executorService1 = Executors.newWorkStealingPool(3);
for(int i = 0; i < 3; i++) {
executorService1.submit(CALLABLE);
}
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
executorService.shutdown();
executorService1.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
- 线程池
通过 submit() 方法创建子线程 来执行任务。
newSingleThreadScheduledExecutor
-
创建一个
单线程化的、定长的线程池。也可以理解为:创建一个单线程执行器。 -
支持定时及周期性任务的执行。 -
它
只有一个线程,用仅有的一个线程来执行任务,保证所有的任务按照指定顺序(FIFO,或 LIFO,或 优先级)执行。 -
所有的任务都
保存在队列 LinkedBlockingQueue 中,等待唯一的单线程来执行任务。 -
是
定长周期任务线程池和单线程线程池的结合版。
public class ThreadPool {
/**
* Runnable 对象
*/
private static final Runnable RUNNABLE = new Runnable() {
@Override
public void run() {
IntStream.range(0, 3).forEach(i -> {
try {
// 休眠 0.5 秒
Thread.sleep(500L);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Runnable 版");
}
});
}
};
/**
* Callable<Integer> 对象
*/
private static final Callable<Integer> CALLABLE = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int integer = 0;
int i = 0;
while(i < 4) {
// 休眠 0.5 秒
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + ",这是第 " + i + "次。Callable<> 版");
integer += i;
i++;
}
return integer;
}
};
/**
* newSingleThreadScheduledExecutor
*/
public static void main(String[] args) {
// 创建线程工厂
TestThreadPollFactory factory = new TestThreadPollFactory("线程工厂 测试,");
// 创建线程池
ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor(factory);
for(int i = 0; i < 3; i++) {
singleThreadScheduledExecutor.submit(RUNNABLE);
}
// 创建线程工厂
TestThreadPollFactory factory1 = new TestThreadPollFactory("单线程的定时任务、周期任务,测试,");
// 创建线程池(传入核心线程数 n 和 线程工厂)
ScheduledExecutorService singleThreadScheduledExecutor1 = Executors.newSingleThreadScheduledExecutor(factory1);
// 定时任务(延迟 1s 后执行,每 3s 一次,按照固定的周期执行)
singleThreadScheduledExecutor1.scheduleAtFixedRate(RUNNABLE, 1, 3, TimeUnit.SECONDS);
// 10 秒后关闭线程池
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("----- ----- 关闭线程池 ----- -----");
// 关闭线程池
singleThreadScheduledExecutor.shutdown();
singleThreadScheduledExecutor1.shutdown();
}
}
}
/**
* 实现线程工厂 ThreadFactory
* <p>
* 线程工厂的作用:创建一个线程
*/
class TestThreadPollFactory implements ThreadFactory {
/**
* 线程名称前缀
*/
private final String threadNamePrefix;
/**
* 整数,用来标记线程
*/
private final AtomicInteger threadIdx = new AtomicInteger(0);
public TestThreadPollFactory(String prefix) {
threadNamePrefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 拼接结果 -> 线程工厂 测试,线程:n
thread.setName(threadNamePrefix + "线程:" + threadIdx.getAndIncrement());
return thread;
}
}
-
线程池
通过 submit() 方法创建子线程 来执行任务。 -
同时,
通过 schedule()、scheduleAtFixedRate()、scheduleWithFixedDelay() 方法执行定时、周期任务。
线程池的分类
无界线程池
-
并不是可以无限大(线程无限多),而是池中最多可以有 127 个线程。 -
空闲线程会在 60 s 后回收。 -
创建方法例子:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
指定大小的线程池
-
是
指定线程数量的线程池,任务数大于线程数时,任务阻塞。 -
创建方法例子:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
定长线程池、周期任务线程池
-
是
指定核心线程数量的线程池,任务数大于核心线程数时,任务阻塞。 -
支持定时及周期性任务的执行。 -
创建方法例子:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
单线程线程池
-
是指:
核心线程有且仅有一个的线程池。也可以理解为:创建一个单线程执行器。 -
保证
所有的任务按照指定顺序(FIFO,或 LIFO,或 优先级)执行。 -
创建方法例子:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
并发线程池
-
是一个
并发的线程池。默认将 CPU 的数量作为传入参数。 -
能够合理的使用 CPU 进行对任务操作(并行操作)。
-
适合使用在很耗时的任务中。 -
是真正意义上的并发,任务执行顺序不定,与任务开始时间无关。
-
创建方法例子:
ExecutorService executorService = Executors.newWorkStealingPool();
单线程定长线程池、单线程周期任务线程池
-
是指:
核心线程有且仅有一个的线程池。 -
支持定时及周期性任务的执行。
-
创建方法例子:
ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();