目录
CyclicBarrier和CountDownLatch的区别
如何控制多线程的执行顺序
- 使用线程的join方法
- 使用主线程的join方法
- 使用对象的wait和notify方法
- 使用单线程的线程池
- 使用AQS的Condition(条件变量)
- 使用CountDownLatch
- 使用CyclicBarrier(回环栅栏)
- 使用Semaphore(信号量)
- 使用CompletableFuture
线程池的优点
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
线程池的创建
ThreadPoolExecutor mExecute = new ThreadPoolExecutor(
corePoolSize, //线程池的核心线程数
maximumPoolSize,//线程池所能容纳的最大线程数
keepAliveTime,//线程的空闲时间
TimeUnit.SECONDS,//keepAliveTime对应的单位
workQueue,//线程池中的任务队列
threadFactory, //线程工厂
rejectHandler//当任务无法被执行时的拒绝策略
);
线程池的工作原理
当有请求到来时:
1.若当前实际线程数量 少于 corePoolSize,即使有空闲线程,也会创建一个新的工作线程;
2 若当前实际线程数量处于corePoolSize和maximumPoolSize之间,并且阻塞队列没满,则任务将被放入阻塞队列中等待执行;
3.若当前实际线程数量 小于 maximumPoolSize,但阻塞队列已满,则直接创建新线程处理任务;
4.若当前实际线程数量已经达到maximumPoolSize,并且阻塞队列已满,则使用饱和策略

4种线程池
1.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
线程池4种拒绝策略
AbortPolicy
这种拒绝策略在拒绝任务时,会直接抛出一个类型为 RejectedExecutionException 的 RuntimeException,让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。
DiscardPolicy
当有新任务被提交后直接被丢弃掉,也不会给你任何的通知,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
DiscardOldestPolicy
丢弃任务队列中的头结点,通常是存活时间最长的任务,它也存在一定的数据丢失风险。
CallerRunsPolicy(常用)
当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。这样做主要有两点好处:
第一点新提交的任务不会被丢弃,这样也就不会造成业务损失。 第二点好处是,由于谁提交任务谁就要负责执行任务,这样提交任务的线程就得负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期。
线程的状态


如何查看线程死锁
1.可以通过jstack命令来查看发生死锁的线程
2 .或者两个线程去操作数据库时,数据库发生了死锁,这是可以查询数据库的死锁情况
1.查询是否锁表
show OPEN TABLES where In_use > 0;
2.查询进程
show processlist;
3.查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
4.查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
写一个死锁
public class DeadLock implements Runnable{
private int flag = 1;
private static final Object o1 = new Object();
private static final Object o2 = new Object();
public void setFlag(int flag) {
this.flag = flag;

本文详细介绍了Java中多线程的控制策略,如join、CountDownLatch等,并探讨了线程池的创建、工作原理及四种线程池类型。同时,分析了线程池的四种拒绝策略和如何避免线程死锁,以及synchronized与ReentrantLock、Lock的区别。此外,还讲解了wait()、sleep()方法的不同,submit与execute的区别,以及线程安全相关的类如ThreadLocal和并发工具类。文章最后讨论了CAS和AQS在并发控制中的作用,以及AtomicInteger的实现原理。
最低0.47元/天 解锁文章
2162

被折叠的 条评论
为什么被折叠?



