java多线程新

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

目录

如何控制多线程的执行顺序

线程池的优点

线程池的创建

线程池的工作原理

​编辑4种线程池

线程池4种拒绝策略

线程的状态

如何查看线程死锁

写一个死锁

产生死锁的条件?如何避免死锁?

synchronized和ReentrantLock的区别

synchronized和 Lock 的区别

wait() 和 sleep()方法有什么不同?

​编辑submit与execute区别

stop()和 suspend()方法的区别

notify和notifyAll方法的区别

CyclicBarrier和CountDownLatch的区别

AQS原理:

AtomicInteger底层实现原理?

voliate 的实现原理

happens-before原则有哪些

ThreadLocal

ThreadLocal如何为每个线程创建变量的副本

什么是CAS

什么是AQS


如何控制多线程的执行顺序

  1. 使用线程的join方法
  2. 使用主线程的join方法
  3. 使用对象的wait和notify方法
  4. 使用单线程的线程池
  5. 使用AQS的Condition(条件变量)
  6. 使用CountDownLatch
  7. 使用CyclicBarrier(回环栅栏)
  8. 使用Semaphore(信号量)
  9. 使用CompletableFuture

线程池的优点

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

线程池的创建

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;
 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值