wait | sleep | |
调用者 | Object对象 | Thread类静态调用 |
释放锁 | Y | N |
使用范围 | 与notify成组使用、用于线程通信 | 单独使用、哪里都可以用 |
异常捕获 | 可以不捕获 |
-
synchronized 和 Lock 区别:
synchronized | java.util.concurrent.locks.Lock | |
语法 | 关键字 | 接口 |
尝试获取锁 | N、若A获得则B一直等待 | Y、可尝试获取若失败则放弃 |
自动释放锁 | Y | N |
公平锁 | N | 默认非公平、可设置 |
精准控制 | N、适合代码量小的同步 | Y |
-
synchronized锁的是谁?static synchronized 或 synchronized(xxx.class) 锁的是class模板对象、否则锁的是调用者。
-
线程编码口诀:线程操作资源类
-
Callable接口与Runnable区别
synchronized Runnable 返回值 Y N 声明抛出异常 Y
注:当线程池中Callable任务运行异常时、异常会被抛到外部、外部可通过ExecutionException捕捉到N
注:当线程池中Runnable任务运行异常时、异常不会被抛到外部、需在run方法中处理
Future接口
方法 | 含义 |
get() | 获取结果(阻塞) |
get(long timeout, TimeUnit unit) | 在指定时间内获取结果(阻塞) |
isDone() | 任务是否已完成(非阻塞) |
cancel(boolean mayInterruptIfRunning) | 取消任务,并返回命令是否发送成功 注:只要发送成功就返回true,和任务是否确实被取消无关 |
任务是否已被取消 注: 1.当使用cancel(false)时,isCancelled()=true也不表示任务已中断; 2.当使用cancel(true)时,isCancelled()=true也不表示任务已中断,是否中断成功依赖于 if (Thread.currentThread().isInterrupted()) 代码块 |
-
线程之间通信:判断、执行、通知
-
虚假唤醒问题:使用while进行条件判断
-
生产者/消费者问题synchronized和JUC版实现对比:
synchronized | JUC版 | |
判断条件 | Object | Condition |
等待方法 | wait | await |
通知方法 | notify/notifyAll | signal/signalAll |
锁
读写锁:
独占锁(写锁):一次只能被一个线程占有
共享锁(读锁):该锁可以被多个线程占有
自旋锁
偏向锁
常用辅助类
Semaphore 信号量
用途:多线程共享资源争夺、并发线程数量控制、多生产者/多消费者模式;
注意事项:
-
创建对象时传入的permits仅仅是初值,可通过多次调用release动态增加permits
-
创建对象时可传参控制是否公平,默认为非公平
方法 | 可被中断 | 不会被中断 | 尝试获得(非阻塞) | 指定时间内尝试获得 |
获得 | acquire() acquire(int permits) |
acquireUninterruptibly() acquireUninterruptibly(int permits) |
tryAcquire() tryAcquire(int permits) |
tryAcquire(long timeout, TimeUnit unit) tryAcquire(int permits, long timeout, TimeUnit unit) |
释放 | release() release(int permits) |
其他方法:
方法 | 含义 |
availablePermits() | 当前可用许可数 |
drainPermits() | 获取并返回立即可用的许可数、并将可用许可数清零 |
getQueueLength() | 取得等待许可的线程数 |
hasQueuedThreads() | 判断是否有线程在等待许可 |
Exchanger 交换器
用途:2个线程之间传输数据
方法 | 说明 |
exchange(V x) | 没有其他线程来取数据则会阻塞 |
exchange(V x, long timeout, TimeUnit unit) | 指定时间内没有其他线程来取数据,则抛出java.util.concurrent.TimeoutException |
CountDownLatch 减法计数器
用途:控制线程间同步,当计数器变为0的时候继续运行,否则阻塞。
注意事项:计数器无法重置
方法 | 说明 | 抛出异常 |
await() await(long timeout, TimeUnit unit) |
进入等待状态 | InterruptedException |
countDown() | 计数器-1 |
CyclicBarrier 加法计数器
用途:控制线程间同步,当计数器达到指定值的时候继续运行,否则阻塞。
方法 | 说明 | 抛出异常 |
await() | 进入等待状态 | InterruptedException BrokenBarrierException |
await(long timeout, TimeUnit unit) | 进入等待状态有限时间 | InterruptedException BrokenBarrierException TimeoutException |
getNumberWaiting() | 返回已到达屏障点的线程数, 注意:最后一个线程已到达时会返回0; 即假设parties=3,线程1,2 await()方法之后调用getNumberWaiting()=1,2,而线程3 await()方法之后调用getNumberWaiting()=0 |
|
getParties() | 屏障对象个数 | |
reset() | 重置屏障,等待屏障的其他线程会出现BrokenBarrierException |
CountDownLatch和CyclicBarrier区别:
CountDownLatch使用情况为2个角色互等、CyclicBarrier使用情况为同类互等。
Phaser 移相器(CyclicBarrier增强版) since1.7
用途:CyclicBarrier增强版、可动态增减parties计数,可用于线程分组同步控制。
方法 | 说明 |
arrive() | 使getArrivedParties()+1,且不等待其他线程,并重置计数器 |
awaitAdvance(int phase) | 如果参数phase值和当前getPhase()方法返回值一致则等待,否则继续运行,类似旁观者作用,可被中断但不会影响其他线程运行,不抛出InterruptedException |
awaitAdvanceInterruptibly(int phase) | 如果参数phase值和当前getPhase()方法返回值一致则等待,否则继续运行,可被中断但不会影响其他线程运行,抛出InterruptedException |
awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit) | 同上,timeout时会抛出TimeoutException |
arriveAndAwaitAdvance() | 计数不足时会阻塞 |
arriveAndDeregister() | 退出计数,并使parties-1 |
getPhase() | 获取已到达屏障的对象个数 |
getRegisteredParties() | 获取注册的parties数 |
register() | parties+1 |
bulkRegister(int parties) | 批量增加parties |
getArrivedParties() | 获取已经被使用的parties数 |
getUnarrivedParties() | 获取还未被使用的parties数 |
forceTermination() | 取消屏障,线程继续执行后续,不出现异常 |
isTerminated() | 屏障是否已取消 |
实际工作中不推荐直接使用:see《阿里巴巴Java开发手册(终极版)》一、编程规约-(六)并发处理-条目4
线程池大小/线程数
线程池大小与处理器的利用率之比估算公式:N-threads = N-CPU * U-CPU * (1 + W/C)
其中:
❑N-CPU是处理器的核的数目=Runtime.getRuntime().availableProcessors()
❑U-CPU是期望的CPU利用率(该值应该介于0和1之间)
❑W/C是等待时间与计算时间的比率
线程数设定:
-
CPU密集型(计算密集型):
最大线程数=CPU核数=Runtime.getRuntime().availableProcessors(); 推荐使用Stream接口。
-
IO密集型:
最大线程数=IO任务的倍数、不能低于IO任务的数量;使用CompletableFuture灵活性更好。
execute和submit方法区别
execute | submit | |
返回值 | N | Y |
异常 | 默认直接抛出、不能捕获,可通过ThreadFactory方式进行捕获 | 默认可通过catch (ExecutionException e)捕获 |
CompletionService
用途:避免FutureTask阻塞缺点,更有效地处理Future返回值。
方法 | 说明 |
take() | 获取已完成任务的Future(非阻塞),但当存在有任务未能完成时 take().get() 仍会阻塞 |
poll() | 获取并移除已完成任务的Future,不存在则返回null(非阻塞) |
poll(long timeout, TimeUnit unit) | 等待指定时间,无论结果如何均往下执行 |
2步骤:任务拆分、结果合并。
应用场景:大数据量,好处:提高效率、坏处:产生资源争夺
原理:工作窃取(work-stealing)算法、底层使用双端队列
不安全集合类 | 安全集合类 |
ArrayList | CopyOnWriteArrayList |
HashSet | CopyOnWriteArraySet |
HashMap | ConcurrentHashMap |
-
4组API:队列一般可以检测第一个元素是谁!
方法 | 第一组会抛出异常 | 返回一个布尔值,不会抛出异常 | 延时等待 | 一直等待(阻塞) |
插入 | add() | offer(e) | offer(e,time) | put() |
取出 | remove() | poll() | poll(time) | take() |
检查 | element() | peek() | - | - |
非阻塞队列7个
阻塞队列6个
since 1.8
CompletableFuture 异步回调
函数式编程(java.util.function)
lambda表达式:()->{}
4个基本的函数式接口:
-
Function : 有一个输入参数有一个输出参数
-
Consumer:有一个输入参数,没有输出参数
-
Supplier:没有输入参数,只有输出参数
-
Predicate:有一个输入参数,判断是否正确
Stream(java.util.stream)
-
流:从支持数据处理操作的源生成的一系列元素。
-
2类流操作:中间操作、终端操作。
-
流利用内部迭代:迭代通过filter、map、sorted等操作被抽象掉了,filter、map等中间操作会返回一个流,并可以链接在一起,可以用来设置一条流水线,但不会生成结果。
-
forEach和count等终端操作会返回一个非流的值,并处理流水线以返回结果。
-
流中的元素是按需计算的。
阅读《Java 8 in Action》、《Java 8函数式编程》
单例模式实现对比
实现方式 | 可延迟加载 | 多线程环境安全 | |
饿汉式 | N | Y | Y |
懒汉式 | Y | N | Y |
懒汉式+synchronized | Y | Y 但性能低下 | Y |
DCL懒汉式 | Y | Y 但可能产生NPE | Y |
DCL懒汉式+volatile | Y | Y | Y |
Holder方式 | Y | Y | Y |
枚举类式 | N | Y | N |
枚举类+Holder方式 | Y | Y | Y |
原子引用
java.util.concurrent.atomic包
ABA问题
相关推荐
Java.util.concurrent(JUC)是Java平台中的一个核心包,专门用于处理多线程并发问题。这个包包含了大量的工具类和接口,极大地简化了并发编程的复杂性,提高了程序的性能和可伸缩性。本测试源文件主要是针对JUC并发...
首先我们知道,JUC就是java.util.concurrent包,俗称java并发包,那首先我们要知道java并发包是用来干嘛 的,然后要知道java并发包包括哪些知识点,这些知识点在平常中有哪些重要的运用,简单来说,这个学习 方法...
java.util.concurrent java.util.concurrent java.util.locks java.util.atomic 进程/线程 并发/并行 线程 package com.ntuzy.juc_01 ; import java.util.concurrent.Callable ; import java.util.concurrent....
import java.util.concurrent.locks.ReentrantLock; public class Ticket { private final ReentrantLock lock = new ReentrantLock(); public void sale() { lock.lock(); try { // 执行售票逻辑 } ...
JUC(Java Util Concurrent),即Java的并发工具包,是Java提供的一套并发编程解决方案,它通过一系列接口和类简化了并发编程的复杂性。本笔记整理涉及了JUC的内存可见性、volatile关键字以及CAS算法和原子变量等多...
J.U.C并发包,即java.util.concurrent包,是JDK的核心工具包,是JDK1.5之后,由 Doug Lea实现并引入。
Java并发编程领域中的JUC(Java Util Concurrency)是一门深奥且实用的技术,它包含在Java的`java.util.concurrent`包中,为多线程编程提供了高效、易用的工具。这个压缩包文件“个人学习JUC代码笔记总集”显然是一...
Java并发编程主要涉及java.util.concurrent包,包括并发工具类、原子类和锁。其中: - **java.util.concurrent** 包含并发工具类,如ExecutorService、Semaphore、CountDownLatch等。 - **java.util.concurrent....
JUC(Java Util Concurrent)是Java中用于并发编程的工具包,它提供了一系列用于多线程编程的类和接口,以帮助开发者实现高效的多线程程序。在并发编程中,我们需要理解几个核心概念,比如线程和进程,以及它们之间...
import java.util.concurrent.locks.ReentrantLock; public class TicketSale { private final ReentrantLock lock = new ReentrantLock(); private int tickets = 100; // 假设共有100张票 public void ...
【狂神说JUC代码】是一系列专注于Java并发编程(JUC,Java Util Concurrency)的教程或笔记,旨在帮助开发者深入理解并掌握Java平台上的并发处理机制。JUC是Java标准库中的一组高级并发工具类,为多线程环境下的程序...
在IT行业中,尤其是在Java开发领域,`java.util.concurrent`(JUC)包是并发编程的核心工具包,它提供了丰富的类和接口,使得开发者能够高效、安全地处理多线程环境中的任务。`Concurrent.zip`文件很可能是包含了...
Java并发工具集(JUC,java.util.concurrent)提供了丰富的并发组件,如`ExecutorService`、`Future`、`BlockingQueue`等,帮助开发者高效地编写并发程序。 并发编程的挑战在于正确地管理线程间的通信和同步,避免...
Java中的线程池主要通过`java.util.concurrent`包下的`ExecutorService`接口及其实现类`ThreadPoolExecutor`来实现。 #### 三、`ThreadPoolExecutor`原理 `ThreadPoolExecutor`是Java中最常用的线程池实现类之一,...
无锁编程,也称为Lock-Free Programming,是指在多线程环境下,通过避免使用传统的锁机制(如synchronized或java.util.concurrent.locks.Lock)来同步对共享数据的访问。这种技术依赖于原子操作(如CAS - Compare ...
### Java并发编程笔记 #### 一、线程与进程 - **进程**: 是操作系统资源分配的基本单位,每个进程都有自己的独立内存空间。例如,当我们打开QQ或者音乐播放器时,实际上是在启动`qq.exe`或`Music.exe`这样的程序,...
Java并发包源码分析(JDK1.8):囊括了java.util.concurrent包中大部分类的源码分析,其中涉及automic包,locks包(AbstractQueuedSynchronizer、ReentrantLock、ReentrantReadWriteLock、LockSupport等),queue...
根据提供的文件信息,我们可以推断出这是一份与Java高级面试相关的资料,主要涉及JVM、JUC(Java Util Concurrency)以及Java多线程高并发等知识点。下面将对这些核心内容进行详细阐述。 ### JVM精讲 #### 1. JVM...
Java Util Concurrent(JUC)是Java并发编程的核心库,提供了丰富的工具和接口,使得开发者能够高效、安全地处理多线程环境中的并发问题。以下将详细介绍JUC中的关键概念和特性。 1. **线程池**:JUC通过Executor...