
Java 并发编程
介绍并发问题的原因
使用 JDK 进行并发编程
使用 JDK 类库进行并发编程实例
并发书籍、视频、站点推荐
ConstXiong
记录编程实践...
展开
-
Executor 如何使用?
Executor 英文意思是执行者,可以看出它的作用是提交和执行任务接口,也可以理解为是线程池。Executor 有一个子接口ExecutorService,ExecutorService 可以管理和终止任务的方法,可以追踪异步任务的进度的Executor。Executors 是线程池的工厂类,提供静态工具方法。使用Executors 可以方便地创建各种类型的线程池。但是由于 Exe...原创 2020-01-03 09:13:23 · 1715 阅读 · 0 评论 -
Java并发原子类有哪些?如何使用?
JDK Atomic开头的类,是通过 CAS 原理解决并发情况下原子性问题 CAS 包含 3 个参数,CAS(V, E, N)。V 表示需要更新的变量,E 表示变量当前期望值,N 表示更新为的值。只有当变量 V 的值等于 E 时,变量 V 的值才会被更新为 N。如果变量 V 的值不等于 E ,说明变量 V 的值已经被更新过,当前线程什么也不做,返回更新失败 当多个线程同时使用 CAS 更新一个...原创 2019-12-30 09:37:16 · 457 阅读 · 0 评论 -
JDK 中有哪些同步容器?并发容器?
JDK 1.5 之前同步容器包括:Vector、Hashtable、Stack Collections 工具类将普通容器,转变为同步容器,如:public static <T> Collection<T> synchronizedCollection(Collection<T> c)public static <T> Set<T&g...原创 2019-12-30 09:24:21 · 412 阅读 · 0 评论 -
CyclicBarrier如何使用?
CyclicBarrier 的中文意思是 "循环栅栏",简单理解就是一个可以循环利用的屏障。 用于让多个线程阻塞在屏障处,当屏障达到放开的条件,所有被阻塞的线程会继续执行,此时 CyclicBarrier 会自动重置。 阻塞线程在屏障处,调用 CyclicBarrier 对象的 await() 方法 CyclicBarrier 内部主要通过了 ReentrantLock 和 Conditio...原创 2019-12-26 09:07:29 · 538 阅读 · 0 评论 -
CountDownLatch如何使用?
CountDownLatch 可以起到发令枪的作用,JDK 1.5 开始提供 用 CountDownLatch 实现并发访问,在写测试工具时希望达到某条件后,所有线程同时执行 也可以用 CountDownLatch 实现,某线程等待其他线程完成,进行最后的统一处理代码如下:package constxiong.interview;import java.util.concur...原创 2019-12-24 19:47:37 · 473 阅读 · 0 评论 -
StampedLock如何使用?
StampedLock 是从 JDK1.8 开始提供,它的性能比 ReadWriteLock 好 StampedLock 支持:乐观读锁、悲观读锁、写锁 StampedLock 的悲观读锁、写锁,与 ReadWriteLock 的读锁、写锁用法相似:读读可并行、读写互斥、写写互斥。 StampedLock 之所以性能优于ReadWriteLock,因为它支持乐观读锁。乐观读锁操作,支持一个...原创 2019-12-24 09:04:31 · 757 阅读 · 0 评论 -
Java中的读写锁ReadWriteLock
ReadWriteLock 是 JDK 中的读写锁接口ReentrantReadWriteLock 是 ReadWriteLock 的一种实现读写锁非常适合读多写少的场景。读写锁与互斥锁的一个重要区别是读写锁允许多个线程同时读共享变量,这是读写锁在读多写少的情况下性能较高的原因。读写锁的原则:多个线程可同时读共享变量 只允许一个线程写共享变量 写线程正在执行写操作,...原创 2019-12-20 09:20:51 · 454 阅读 · 0 评论 -
Condition实现等待、唤醒
Condition 接口是 JDK 1.5 开始提供的,用来实现线程间的等待与唤醒Condition 的对象可以通过 Lock 对象的 newCondition() 方法创建Condition 对象方法的调用必须在 Lock 对象的 lock() 和 unlock() 之间,否则会抛出异常 java.lang.IllegalMonitorStateExceptionConditi...原创 2019-12-11 09:17:21 · 555 阅读 · 1 评论 -
JDK中Atomic开头的原子类实现原子性的原理是什么?
JDK Atomic开头的类,是通过 CAS 原理解决并发情况下原子性问题。 CAS 包含 3 个参数,CAS(V, E, N)。V 表示需要更新的变量,E 表示变量当前期望值,N 表示更新为的值。只有当变量 V 的值等于 E 时,变量 V 的值才会被更新为 N。如果变量 V 的值不等于 E ,说明变量 V 的值已经被更新过,当前线程什么也不做,返回更新失败。 当多个线程同时使用 CAS 更新...原创 2019-12-11 09:09:55 · 540 阅读 · 0 评论 -
什么是协程?Java中如何支持?
协程(Coroutine):是单线程下的并发,又称微线程,纤程。简单理解就是线程中的线程。优点: 轻量,创建成本小,降低了内存消耗 用户态调度,减少了 CPU 上下文切换的开销,提高了 CPU 缓存命中率 减少同步加锁,提高了性能 可以用同步思维写异步代码 缺点: 在协程执行中不能有阻塞操作,否则整个线程被阻塞 不擅长处理 C...原创 2019-12-05 19:52:47 · 1295 阅读 · 0 评论 -
为什么要用并发编程?
1、"摩尔定律" 失效,硬件的单元计算能力提升受限;硬件上提高了 CPU 的核数和个数。并发编程可以提升 CPU 的计算能力的利用率。2、提升程序的性能,如:响应时间、吞吐量、计算机资源使用率等。3、并发程序可以更好地处理复杂业务,对复杂业务进行多任务拆分,简化任务调度,同步执行任务。【Java面试题与答案】整理推荐基础与语法 集合 网络编程 并发编程 Web 安全...原创 2019-08-25 00:48:17 · 3673 阅读 · 0 评论 -
什么是并发编程?
并发:在程序设计的角度,希望通过某些机制让计算机可以在一个时间段内,执行多个任务。 一个或多个物理 CPU 在多个程序之间多路复用,提高对计算机资源的利用率。 任务数多余 CPU 的核数,通过操作系统的任务调度算法,实现多个任务一起执行。 有多个线程在执行,计算机只有一个 CPU,不可能真正同时运行多个线程,操作系统只能把 CPU 运行时间划分成若干个时间段,再将时间段分配给各个线程执行...原创 2019-08-23 23:21:36 · 4721 阅读 · 0 评论 -
带着问题重学 Java 并发编程
基本概念什么是并发编程?为什么要用并发编程?并发编程的缺点?并行是什么意思?与并发的区别是什么?什么是线程?什么是进程?为什么要有线程?有什么关系与区别?如何创建、启动 Java 线程?如何优雅地停止一个线程?什么是守护线程?线程包括哪些状态?状态之间是如何变化的?什么是线程池?Executors如何创建线程池?线程池包含哪些状态?如何停止一个线...原创 2019-08-23 00:44:44 · 4238 阅读 · 1 评论 -
导致并发程序出问题的根本原因是什么?
CPU、内存、IO 设备的读写速度差异巨大,表现为 CPU 的速度 >内存的速度 > IO 设备的速度。程序的性能瓶颈在于速度最慢的 IO 设备的读写,也就是说当涉及到 IO 设备的读写,再怎么提升 CPU 和内存的速度也是起不到提升性能的作用。为了更好地利用 CPU 的高性能计算机体系结构,给 CPU 增加了缓存,均衡 CPU 和内存的速度差异 操作系统,...原创 2019-09-14 22:44:01 · 2459 阅读 · 1 评论 -
什么是 happens-before 原则?
Java 中happens-before 原则,是在 JSR-133 中提出的。原文摘要:• Each action in a thread happens-before every subsequent action in that thread.• An unlock on a monitor happens-before every subsequent lock on tha...原创 2019-10-10 12:20:06 · 958 阅读 · 0 评论 -
线程池包含哪些状态?
线程池状态:线程池的5种状态:RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED。见 ThreadPoolExecutor 源码// runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; ...原创 2019-09-10 23:24:44 · 2919 阅读 · 1 评论 -
Executors如何创建线程池?
Executors如何创建线程池?Executors 类是从 JDK 1.5 开始就新增的线程池创建的静态工厂类,它就是创建线程池的,但是很多的大厂已经不建议使用该类去创建线程池。原因在于,该类创建的很多线程池的内部使用了无界任务队列,在并发量很大的情况下会导致 JVM 抛出 OutOfMemoryError,直接让 JVM 崩溃,影响严重。但是 Executors 类究竟是如何使用...原创 2019-09-09 09:38:37 · 1438 阅读 · 0 评论 -
什么是线程池?
什么是线程池?线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,处理完之后线程并不会被销毁,而是仍然在线程池中等待下一个任务。为什么要使用线程池?因为 Java 中创建一个线程,需要调用操作系统内核的 API,操作系统要为线程分配一系列的资源,成本很高,所以线程是一个重量级的对象,应该避免频繁创建和销毁。使用线程池就能很好地避免...原创 2019-09-07 20:12:44 · 1644 阅读 · 0 评论 -
线程包括哪些状态?状态之间是如何转变的?
线程的生命周期线程包括哪些状态的问题说专业一点就是线程的生命周期。不同的编程语言对线程的生命周期封装是不同的。Java 中线程的生命周期Java 语言中线程共有六种状态。NEW(初始化状态) RUNNABLE(可运行 / 运行状态) BLOCKED(阻塞状态) WAITING(无限时等待) TIMED_WAITING(有限时等待) TERMINATED(终止状态)...原创 2019-09-04 23:25:12 · 3194 阅读 · 1 评论 -
什么是守护线程?
Java线程分为用户线程和守护线程。守护线程是程序运行的时候在后台提供一种通用服务的线程。所有用户线程停止,进程会停掉所有守护线程,退出程序。Java中把线程设置为守护线程的方法:在 start 线程之前调用线程的 setDaemon(true) 方法。注意:setDaemon(true) 必须在 start() 之前设置,否则会抛出IllegalThreadStateExc...原创 2019-09-03 12:31:57 · 8423 阅读 · 2 评论 -
如何优雅地停止一个线程?
线程终止有两种情况:1、线程的任务执行完成2、线程在执行任务过程中发生异常这两者属于线程自行终止,如何让线程 A 把线程 B 终止呢?Java 中 Thread 类有一个 stop() 方法,可以终止线程,不过这个方法会让线程直接终止,在执行的任务立即终止,未执行的任务无法反馈,所以 stop() 方法已经不建议使用。既然 stop() 方法如此粗暴,不建议使用,我...原创 2019-09-03 09:11:57 · 3921 阅读 · 0 评论 -
如何创建、启动 Java 线程?
Java 中有 4 种常见的创建线程的方式。一、重写 Thread 类的 run() 方法。 表现形式有两种:1)new Thread 对象匿名重写 run() 方法package constxiong.concurrency.a006; /** * new Thread 对象匿名重写 run() 方法,启动线程 * @author ConstXiong */...原创 2019-09-02 10:19:18 · 1789 阅读 · 0 评论 -
什么是线程?什么是进程?为什么要有线程?有什么关系与区别?
什么是线程?什么是进程?为什么要有线程?有什么关系与区别?进程: 程序执行时的一个实例 每个进程都有独立的内存地址空间 系统进行资源分配和调度的基本单位 进程里的堆,是一个进程中最大的一块内存,被进程中的所有线程共享的,进程创建时分配,主要存放 new 创建的对象实例 进程里的方法区,是用来存放进程中的代码片段的,是线程共享的 在多线程 OS 中,进程不是一个可执行的实...原创 2019-08-27 20:34:53 · 5207 阅读 · 0 评论 -
并行是什么意思?与并发的区别是什么?
并行是什么意思?与并发的区别是什么?并行:指两个或两个以上事件或活动在同一时刻发生。如多个任务在多个 CPU 或 CPU 的多个核上同时执行,不存在 CPU 资源的竞争、等待行为。并行与并发的区别1、并行指多个事件在同一个时刻发生;并发指在某时刻只有一个事件在发生,某个时间段内由于 CPU 交替执行,可以发生多个事件。2、并行没有对 CPU 资源的抢占;并发执行的线程...原创 2019-08-26 21:30:22 · 15800 阅读 · 0 评论 -
什么是 Java 内存模型?
在了解什么是 Java 内存模型之前,先了解一下为什么要提出Java 内存模型。之前提到过并发编程有三大问题CPU 缓存,在多核 CPU 的情况下,带来了可见性问题 操作系统对当前执行线程的切换,带来了原子性问题 译器指令重排优化,带来了有序性问题为了解决并发编程的三大问题,提出了 JSR-133,新的 Java 内存模型,JDK 5 开始使用。那么什么是Java 内存...原创 2019-10-09 00:40:59 · 705 阅读 · 0 评论 -
Java 中有哪些无锁技术来解决并发问题?如何使用?
除了使用 synchronized、Lock 加锁之外,Java 中还有很多不需要加锁就可以解决并发问题的工具类1、原子工具类JDK 1.8 中,java.util.concurrent.atomic 包下类都是原子类,原子类都是基于sun.misc.Unsafe 实现的。CPU 为了解决并发问题,提供了 CAS 指令,全称 Compare And Swap,即比较并交互 C...原创 2019-09-29 00:20:17 · 1499 阅读 · 6 评论 -
Java 隐式锁 - synchronized 关键字
Java 中关键字synchronized表示只有一个线程可以获取作用对象的锁,执行代码,阻塞其他线程。作用:确保线程互斥地访问同步代码 保证共享变量的修改能够及时可见 有效解决重排序问题用法:修饰普通方法 修饰静态方法 指定对象,修饰代码块特点: 阻塞未获取到锁、竞争同一个对象锁的线程 获取锁无法设置超时 无法实现公平锁 控制等待和唤醒需要...原创 2019-09-15 21:47:15 · 984 阅读 · 0 评论 -
Java 中的 volatile 关键字
Java 中volatile 关键字是一个类型修饰符。JDK 1.5 之后,对其语义进行了增强。保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了共享变量的值,共享变量修改后的值对其他线程立即可见 通过禁止编译器、CPU 指令重排序和部分 happens-before 规则,解决有序性问题volatile 可见性的实现在生成汇编代码指令时会在 volatile 修饰的...原创 2019-09-17 21:11:41 · 1027 阅读 · 0 评论 -
Java 中的锁
今天是九一八事变爆发 88 周年,国耻日。每当我看到祖国的航空航天、互联网、5G 这些科技方面赶超美国的新闻时,我内心都异常激动,从 "东亚病夫" 到吾辈自强,靠得是无数中华儿女的实干。铭记历史...工作再忙,还是希望坚持把编程知识分享下去,继续 Java 并发编程。在并发编程中,经常会遇到多个线程访问同一个共享变量,当同时对共享变量进行读写操作时,就会产生数据不一致的情况。...原创 2019-09-18 22:23:33 · 707 阅读 · 0 评论 -
Java 中的锁如何使用?有什么注意事项?
Java 中常见的锁有synchronized 可重入锁 java.util.concurrent.lock.ReentrantLock 可重复读写锁 java.util.concurrent.lock.ReentrantReadWriteLocksynchronized 有 3种用法修饰普通方法,执行方法代码,需要获取对象本身 this 的锁package constxi...原创 2019-09-19 20:47:07 · 1052 阅读 · 0 评论 -
如何停止一个线程池?
Java 并发工具包中java.util.concurrent.ExecutorService 接口定义了线程池任务提交、获取线程池状态、线程池停止的方法等。JDK 1.8 中,线程池的停止一般使用shutdown()、shutdownNow()、shutdown() + awaitTermination(long timeout, TimeUnit unit) 方法。1、...原创 2019-09-13 18:26:37 · 3038 阅读 · 0 评论 -
Java 中锁之间的对比
synchronized 和 java.util.concurrent.lock.Lock 之间的区别实现层面不一样。synchronized 是 Java 关键字,JVM层面 实现加锁和释放锁;Lock 是一个接口,在代码层面实现加锁和释放锁 是否自动释放锁。synchronized 在线程代码执行完或出现异常时自动释放锁;Lock 不会自动释放锁,需要在finally {} 代码块显...原创 2019-09-21 22:44:24 · 614 阅读 · 0 评论 -
如何避免死锁
并发程序一旦死锁,往往我们只能重启应用。解决死锁问题最好的办法就是避免死锁。死锁发生的条件互斥,共享资源只能被一个线程占用 占有且等待,线程 t1 已经取得共享资源 s1,尝试获取共享资源 s2 的时候,不释放共享资源 s1 不可抢占,其他线程不能强行抢占线程 t1 占有的资源 s1 循环等待,线程 t1 等待线程 t2 占有的资源,线程 t2 等待线程 t1 占有的资源...原创 2019-09-24 20:27:54 · 1159 阅读 · 0 评论 -
什么是活锁和饥饿?及示例
活锁任务没有被阻塞,由于某些条件没有满足,导致一直重复尝试—失败—尝试—失败的过程。 处于活锁的实体是在不断的改变状态,活锁有可能自行解开。死锁是大家都拿不到资源都占用着对方的资源,而活锁是拿到资源却又相互释放不执行。解决活锁的一个简单办法就是在下一次尝试获取资源之前,随机休眠一小段时间。看一下,我们之前的一个例子,如果最后不进行随机休眠,就会产生活锁,现象就是很长一段...原创 2019-09-26 09:28:05 · 2307 阅读 · 0 评论 -
带着问题重学 Java 并发编程
基本概念什么是并发编程?为什么要用并发编程?并发编程的缺点?并行是什么意思?与并发的区别是什么?什么是线程?什么是进程?为什么要有线程?有什么关系与区别?如何创建、启动 Java 线程?如何优雅地停止一个线程?什么是守护线程?线程包括哪些状态?状态之间是如何变化的?什么是线程池?Executors如何创建线程池?线程池包含哪些状态?如何停止一个线...原创 2019-09-26 09:42:26 · 1198 阅读 · 0 评论 -
Java中的线程等待和唤醒
用死循环的方式,一直尝试获取锁。在任务耗时比较长或者并发冲突比较大的时候,就不适合。因为任务耗时比较长或者并发冲突比较大的时候,可能要循环上万次都不止,才能获取到锁,太消耗 CPU 。这种场景下,理想的解决方案:线程执行任务的条件不满足时,阻塞自己,进入等待状态;当线程执行的任务条件满足时,通知等待的线程继续执行。 线程阻塞的方式,能够避免循环等待对 CPU 的消耗。在...原创 2019-09-28 09:19:04 · 1216 阅读 · 0 评论 -
Java 中可重入锁、不可重入锁的测试
可重入锁指在同一个线程在外层方法获取锁的时候,进入内层方法会自动获取锁。为了避免死锁的发生,JDK 中基本都是可重入锁。下面我们来测试一下 synchronized 和java.util.concurrent.lock.ReentrantLock 锁的可重入性测试 synchronized 加锁 可重入性package constxiong.concurrency.a...原创 2019-09-20 18:32:32 · 765 阅读 · 0 评论