多线程的创建
0x00 多线程的创建
有以下4种创建线程的方法
1. 继承Thread类
1 |
|
2. 实现Runnable接口
1 |
|
3. 实现Callable接口
1 |
|
4. 使用线程池
1 |
|
0x01 线程池基本使用
1. 线程池的创建
1 |
|
2. 线程池的关闭
1 |
|
3. 线程池的执行
无需线程返回数据时使用execute 直接执行线程.
1 |
|
4. 线程池的提交
当需要线程返回数据时使用submit 提交线程. 并使用Future 获取线程返回的数据.
如果这时调用executorService.shutdown()
线程池会等待全部线程执行完毕再关闭.
1 |
|
0x02 几种不同的线程池
有4种不同的实现线程池, 主要区别在于线程池的容量和线程队列的实现. 除newScheduledThreadPool外使用ThreadPoolExecutor实现,newScheduledThreadPool则使用ScheduledThreadPoolExecutor实现
1. newFixedThreadPool
使用LinkedBlockingQueue 作为线程队列.
1 |
|
2. newCachedThreadPool
使用SynchronousQueue作为线程队列.
1 |
|
3. newSingleThreadExecutor
顾名思义单单线程池, 只有一个线程.
1 |
|
4. newScheduledThreadPool
使用DelayedWorkQueue作为线程队列.
1 |
|
0x03 线程池的参数
线程池的参数有:
- corePoolSize: 线程池的核心线程数. 当线程池中的线程数小于corePoolSize时, 会创建新的线程. 当线程池中的线程数大于corePoolSize时, 会使用线程队列.
- maximumPoolSize: 线程池的最大线程数. 当线程池中的线程数大于maximumPoolSize时, 会使用线程队列.
- keepAliveTime: 线程池中线程的空闲时间. 当线程池中的线程空闲时间大于keepAliveTime时, 会销毁线程.
- unit: keepAliveTime的单位.
- workQueue: 线程队列. 当线程池中的线程数大于corePoolSize时, 会使用线程队列. 线程队列的实现有:
- ArrayBlockingQueue: 有界队列, 使用数组实现.
- LinkedBlockingQueue: 无界队列, 使用链表实现.
- SynchronousQueue: 同步队列, 没有容量, 每个插入操作必须等待一个移除操作.
- PriorityBlockingQueue: 优先队列, 使用堆实现.
- threadFactory: 线程工厂. 用于创建线程. 默认使用Executors.defaultThreadFactory()创建.
- handler: 拒绝策略. 当线程池中的线程数大于maximumPoolSize时, 会使用拒绝策略. 默认使用AbortPolicy()拒绝策略.
- AbortPolicy: 拒绝策略, 当线程池中的线程数大于maximumPoolSize时, 会抛出RejectedExecutionException异常.
- CallerRunsPolicy: 拒绝策略, 当线程池中的线程数大于maximumPoolSize时, 会使用调用者所在的线程来执行任务.
- DiscardPolicy: 拒绝策略, 当线程池中的线程数大于maximumPoolSize时, 会丢弃任务.
- DiscardOldestPolicy: 拒绝策略, 当线程池中的线程数大于maximumPoolSize时, 会丢弃队列中最老的任务.
1
2
3
4
5
6
7
8
9ExecutorService executorService = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler
);
0x04 几种Queue
SynchronousQueue
特性:
- SynchronousQueue 是一种特殊的无界队列,它实际上并不存储任何元素。
- 当一个线程试图通过 put 方法插入一个元素时,该操作会一直阻塞,直到另一个线程通过 take 方法取走该元素。
- 同样地,当一个线程尝试从 SynchronousQueue 中获取一个元素时,如果没有其他线程放入元素,该操作也会被阻塞。
用途:
- 主要用于线程间的通信,特别是作为生产者消费者模式中的一种传递机制。
- 可以用于实现线程池中的工作窃取模型,在这种模型中,空闲的线程可以从其他繁忙的线程那里窃取任务来执行。
LinkedBlockingQueue
特性:
- LinkedBlockingQueue 是一个基于链表结构的阻塞队列,它提供了容量可配置的能力。
- 默认情况下,它的容量是 Integer.MAX_VALUE,意味着它可以无限扩展,但在实际应用中,通常会显式指定一个容量限制。
- 如果队列已满,put 操作将阻塞,直到队列中有可用空间。
- 如果队列为空,take 操作将阻塞,直到队列中有新的元素。
用途:
- 适用于需要缓冲处理的数据流场景。
- 适合于生产者消费者模式,其中生产者和消费者的速率可能不一致。
- 在实现线程池时,LinkedBlockingQueue 是一个常见的选择,因为它可以根据实际情况动态调整队列大小。
ArrayBlockingQueue
特性:
- ArrayBlockingQueue 是一个由数组支持的有界阻塞队列。
- 它提供了一个固定大小的缓冲区,用于存储队列中的元素。
- 当队列满了时,put 操作会阻塞,直到队列中有可用空间。
- 当队列为空时,take 操作会阻塞,直到队列中有新的元素。
用途:
- 适用于需要对队列的大小进行限制的场景。
- 适合于生产者消费者模式,其中生产者和消费者的速率可能不一致,但队列的大小是有限的。
PriorityBlockingQueue
特性:
- PriorityBlockingQueue 是一个无界的优先级阻塞队列。
- 它使用优先级堆(类似于最小堆或最大堆)来维护队列中的元素。
- 元素会被按照自然排序顺序或通过比较器确定的顺序进行排序。
- take 方法总是返回并移除优先级最高的元素。
- offer 方法可以在不阻塞的情况下添加元素,但如果队列已满,put 操作会阻塞,直到队列中有可用空间。
用途:
- 适用于需要根据优先级来调度任务的场景。
- 适合于实现优先级队列,比如在调度算法中按照任务的优先级来决定执行顺序。
文章标题:多线程的创建
本文作者:zhu8fei
发布时间:2024-08-14, 09:31:21
最后更新:2024-08-15, 09:37:02
原始链接:http://www.zhu8fei.com/2024/08/14/thread-create.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 zhu8fei@163.com