Merge pull request #21 from HuaHero/HuaHero-patch-19

Update Java 并发.md
This commit is contained in:
HuaHero 2023-11-09 15:40:22 +08:00 committed by GitHub
commit aa9c0479e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -213,7 +213,8 @@ public void run() {
**关于线程池**
【线程池的意义】
线程池可以有效地管理线程:它可以**管理线程的数量**,可以避免无节制的创建线程,导致超出系统负荷直至崩溃。它还可以**让线程复用**,可以大大地减少创建和销毁线程所带来的开销。
【**线程池的核心参数**】 线程池需要依赖一些参数来控制任务的执行流程,其中最重要的参数有corePoolSize核心线程数、workQueue等待队列、maxinumPoolSize最大线程数、handler拒绝策略、keepAliveTime空闲线程存活时间
【**线程池的核心参数**】
线程池需要依赖一些参数来控制任务的执行流程,其中最重要的参数有corePoolSize核心线程数、workQueue等待队列、maxinumPoolSize最大线程数、handler拒绝策略、keepAliveTime空闲线程存活时间
【线程池的运作步骤】
当我们向线程池提交一个任务之后,线程池按照如下步骤处理这个任务:
1. 判断线程数是否达到corePoolSize,若没有则新建线程执行该任务,否则进入下一步。
@ -755,13 +756,21 @@ after
![线程状态转换图](..\assets\1641890623956-ani--线程状态转换.jpg)
## 七、J.U.C - AQS(AbstractQueuedSynchornizer)
**关于AQS**
AbstractQueuedSynchronizer是**队列同步器,是用来构建锁的基础框架**,Lock实现类都是基于AQS实现的。AQS是基于**模板方法模式进行设计的,所以锁的实现需要继承AQS并重写它指定的方法**。A**QS内部定义了一个FIFO的队列来实现线程的同步,同时还定义了同步状态来记录锁的信息**。 AQS的模板方法,将管理同步状态的逻辑提炼出来形成标准流程,这些方法主要包括:独占式获取同步状态、独占式释放同步状态、共享式获取同步状态、共享式释放同步状态。以独占式获取同步状态为例,它的大致流程是:
1. 尝试以独占方式获取同步状态。
2. 如果状态获取失败,则将当前线程加入同步队列。
3. 自旋处理同步状态,如果当前线程位于队头,则唤醒它并让它出队,否则使其进入阻塞状态。 其中,有些步骤无法在父类确定,则提炼成空方法留待子类实现。例如,第一步的尝试操作,对于公平锁和非公平锁来说就不一样,所以子类在实现时需要按照场景各自实现这个方法。 AQS的同步队列,是一个双向链表,AQS则持有链表的头尾节点。对于尾节点的设置,是存在多线程竞争的,所以采用CAS的方式进行修改。对于头节点设置,则一定是拿到了同步状态的线程才能处理,所以修改头节点不需要采用CAS的方式。 AQS的同步状态,是一个int类型的整数,它在表示状态的同时还能表示数量。通常情况下,状态为0时表示无锁,状态大于0时表示锁的重入次数。另外,在读写锁的场景中,这个状态标志既要记录读锁又要记录写锁。于是,锁的实现者就将状态表示拆成高低两部分,高位存读锁、低位存写锁。 加分回答 同步状态需要在并发环境下修改,所以需要保证其线程安全。由于AQS本身就是锁的实现工具,所以不适合用锁来保证其线程安全,因为如果你用一个锁来定义另一个锁的话,那干脆直接用synchronized算了。实际上,同步状态是被volatile修饰的,该关键字可以保证状态变量的内存可见性,从而解决了线程安全问题。(来自https://www.nowcoder.com/exam/interview/75826387/test?paperId=50270024)
java.util.concurrentJ.U.C大大提高了并发性能AQS 被认为是 J.U.C 的核心。
1. **原子类** 从JDK 1.5开始,并发包下提供了atomic子包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。在atomic包里一共提供了17个类,属于4种类型的原子更新方式,分别是原子更新基本类型、原子更新引用类型、原子更新属性、原子更新数组。
2. **锁** 从JDK 1.5开始,并发包中新增了Lock接口以及相关实现类用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。虽然它缺少了隐式获取释放锁的便捷性,但是却拥有了多种synchronized关键字所不具备的同步特性,包括:**可中断地获取锁**、**非阻塞地获取锁**、**可超时地获取锁**。
3. **线程池** 从JDK 1.5开始,并发包下新增了内置的线程池。其中,ThreadPoolExecutor类代表常规的线程池,而它的子类ScheduledThreadPoolExecutor对定时任务提供了支持,在子类中我们可以周期性地重复执行某个任务,也可以延迟若干时间再执行某个任务。此外,Executors是一个用于创建线程池的工具类,由于该类创建出来的是带有无界队列的线程池,所以在使用时要慎重。
3. **线程池** 从JDK 1.5开始,并发包下新增了内置的线程池。其中,**ThreadPoolExecutor**类代表常规的线程池,而它的子类ScheduledThreadPoolExecutor对定时任务提供了支持,在子类中我们可以周期性地重复执行某个任务,也可以延迟若干时间再执行某个任务。此外,Executors是一个用于创建线程池的工具类,由于该类创建出来的是带有无界队列的线程池,所以在使用时要慎重。
4. **并发容器** 从JDK 1.5开始,并发包下新增了大量高效的并发的容器,这些容器按照实现机制可以分为三类。第一类是以**降低锁粒度来**提高并发性能的容器,它们的类名以Concurrent开头,如ConcurrentHashMap。第二类是采用**写时复制技术实**现的并发容器,它们的类名以CopyOnWrite开头,如CopyOnWriteArrayList。第三类是采用**Lock实现的阻塞队列,内部创建两个Condition分别用于生产者和消费者的等待**,这些类都实现了BlockingQueue接口,如ArrayBlockingQueue。