![](https://img-blog.csdnimg.cn/20190927151053287.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
Java 并发编程
文章平均质量分 52
Java 并发编程相关
明月燃雨
人生没有白走的路,每一步都算数。
展开
-
ThreadLocal 详解
1. ThreadLocal 是用来干什么的ThreadLocal 是一个以 ThreadLocal 对象为键、任意对象为值的存储结构,这个结构被附带在线程上,也就是说一个线程可以根据一个 ThreadLocal 对象查询到一个绑定在这个线程上的值。2. ThreadLocal 示例代码如下:public class TestThreadLocal { private static final ThreadLocal<String> STRING_THREAD_LOCAL = n原创 2021-01-02 21:19:48 · 7586 阅读 · 3 评论 -
生产者和消费者
wait / notifywait 会释放锁,但 notify 不会释放锁。public class MyContainer1<T> { private final LinkedList<T> list = new LinkedList<>(); // 最多存 10 个元素 private final int MAX = 10; private int count = 0; public synchronized void p原创 2021-01-01 17:56:39 · 202 阅读 · 2 评论 -
并发工具类之 LockSupport
当需要阻塞或唤醒一个线程的时候,我们可以使用 LockSupport 工具类来完成,它提供的部分方法如下图:测试代码如下:public class TestLockSupport { public static void main(String[] args) { Thread thread = new Thread(() -> { for (int i = 0; i < 10; i++) { System.o原创 2020-12-30 13:50:24 · 120 阅读 · 0 评论 -
并发工具类之 Exchanger
Exchanger (交换者) 是一个用于线程间协作的工具类。Exchanger 用于进行线程间的数据交换。两个线程通过 exchange() 方法交换数据,第一个线程执行到 exchange() 方法后会一直等待第二个线程也执行 exchange() 方法,当两个线程都到达同步点后,这两个线程就可以交换数据。测试代码如下:public class TestExchanger { private static final Exchanger<String> exchanger =原创 2020-12-29 21:57:38 · 185 阅读 · 1 评论 -
并发工具类之 Semaphore
Semaphore (信号量) 是用来控制同时访问特定资源的线程数量,它可以协调各个线程,以保证公共资源被合理使用。Semaphore 可以用于流量控制,特别是公共资源有限的场景,比如数据库连接。假如同时有 10 个线程需要连接数据库,但数据库的连接数只有 2 个,我们必须控制只有 2 个线程能同时获取数据库连接,否则会报错无法获取数据库连接,这时就可以使用 Semaphore 来做流量控制,代码如下:public class TestSemaphore { private static fin原创 2020-12-29 21:38:28 · 152 阅读 · 0 评论 -
ReadWriteLock
写锁是一个支持重进入的排它锁,如果当前线程在获取写锁时,读锁已经被获取或者当前线程不是已经获取写锁的线程,则当前线程进入等待状态。读锁是一个支持重进入的共享锁,它可以被多个线程同时获取,在写锁未被任何线程获取的时候,读锁总会被成功的获取,如果写锁已被其他线程获取,则当前线程获取读锁失败,进入等待状态,如果写锁已被当前线程获取,则当前线程可以成功获取读锁。利用读写锁的特性我们可以写一个缓存类,代码如下:public class Cache { static Map<String, Ob.原创 2020-12-26 21:03:41 · 112 阅读 · 0 评论 -
并发工具类之 CyclicBarrier
public class T07_CyclicBarrier { public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() { @Override public void run() { System.out.println("满 20 人,发车!");原创 2020-12-26 20:05:47 · 142 阅读 · 0 评论 -
并发工具类之 CountDownLatch
public class T06_CountDownLatch { public static void main(String[] args) { Thread[] threads = new Thread[100]; // 计一个数 latch 100 CountDownLatch latch = new CountDownLatch(threads.length); for (int i = 0; i < threads.l原创 2020-12-26 16:24:20 · 116 阅读 · 1 评论 -
ReentrantLock vs synchronized
ReentrantLock 是完全可以替代 synchronized,synchronized 能干的 ReentrantLock 都能干,但 ReentrantLock 能干的 synchronized 不一定能干,例如:ReentrantLock 提供了 tryLock() 方法,会尝试获取锁,如果获取锁了就返回 true,没获取就返回 false,但无论有没有获取锁,都会继续执行之后的代码;此外 tryLock() 还有一个重载的方法 tryLock(long time, TimeUnit un原创 2020-12-26 15:16:04 · 217 阅读 · 3 评论 -
中断异常测试
在测试中断异常前我们先了解一下 sleep 和 wait 的本质区别:sleep 不会释放同步锁,wait 会释放同步锁。抛出中断异常后会释放同步锁。1. sleep1.1 synchronized测试代码如下:public class Sleep { public static void main(String[] args) { Object o = new Object(); Thread t = new Thread(() -> {原创 2020-12-26 13:56:17 · 651 阅读 · 1 评论 -
Lock 之 tryLock
tryLock 有两个重载的方法,分别如下:boolean tryLock();boolean tryLock(long time, TimeUnit unit) throws InterruptedException;tryLock() 会立马返回一个布尔值,如果获得了锁就返回 false;如果没有获得锁就返回 true。无论是返回 true 还是 false,都会继续执行之后的代码。tryLock(long time, TimeUnit unit) 会等待指定的时间,如果时间到了还没获得锁就返原创 2020-12-25 20:29:25 · 9777 阅读 · 0 评论 -
可重入锁
1. 案例初体验public class T01_ReentrantLock1 { synchronized void m1() { for (int i = 0; i < 10; i++) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(原创 2020-12-12 21:42:07 · 109 阅读 · 0 评论 -
volatile 作用及其实现原理
一、并发编程中的三个概念在并发编程中,我们会遇到三个概念:原子性、可见性、有序性。原子性:一个或多个操作,要么全都执行成功,要么都不执行。可见性:当多个线程共享同一变量时,若其中一个线程对该共享变量进行了修改,那么这个修改对其他线程是可见的。有序性:程序执行的顺序按照代码的先后顺序执行。二、volatile 的作用及其实现原理我们先来列出几个结论:volatile 保证了可见性volatile 在一定程度上保证了有序性volatile 能保证读写操作的原子性,但无法保证复合操作的原子原创 2020-10-31 23:34:28 · 36321 阅读 · 0 评论 -
AtomicLong VS Sync VS LongAdder
AtomicLong VS Sync VS LongAdderpublic class T02_AtomicVsSyncVsLongAdder { static AtomicLong count1 = new AtomicLong(0L); static Long count2 = 0L; static LongAdder count3 = new LongAdder(); public static void main(String[] args) throws Int原创 2020-12-12 20:34:34 · 137 阅读 · 1 评论 -
synchronized 用法详解
一、线程不安全实例我们先来创建一个业务类 TestService,代码如下:public class TestService { private int num; public void addName(String username) { try { if ("a".equals(username)) { num = 100; System.out.println("ThreadA原创 2020-10-31 18:07:45 · 35417 阅读 · 0 评论 -
一文读懂乐观锁与悲观锁
乐观锁何谓乐观锁乐观锁是一种思想,在进行读写操作的时候都不会加锁,但在进行写操作的时候会判断数据是否被修改过,这一点可以使用版本号机制或 CAS 算法实现。乐观锁适用于读多写少的场景,可以提高吞吐量,数据库的**write_condition 机制(通过版本号机制实现)和 JUC 包下的原子变量类(通过 CAS 算法实现)**都是基于乐观锁思想实现的。实现方式1.版本号机制版本号机制一般都是在数据库中加一个 version 字段作为判断依据,举例如下:假设数据库中有一个余额表,balance 字原创 2020-10-24 20:09:12 · 249 阅读 · 0 评论 -
线程优先级详解
线程的优先级是什么在操作系统中,线程可以划分优先级,线程优先级越高,获得 CPU 时间片的概率就越大,但线程优先级的高低与线程的执行顺序并没有必然联系,优先级低的线程也有可能比优先级高的线程先执行。如何设置线程的优先级在 Java 中,可以通过 setPriority(int newPriority) 方法来设置线程的优先级。线程的优先级分为 1~10 一共 10 个等级,所有线程默认优先级为 5,如果优先级小于 1 或大于 10,则会抛出 java.lang.IllegalArgumentExce原创 2020-10-01 22:30:54 · 10300 阅读 · 0 评论 -
如何暂停线程?
一、基础用法和终止线程不同,暂停线程意味着此线程还可以恢复,在 Java 中,可以使用 suspend() 方法暂停线程,然后使用 resume() 方法恢复线程的执行。首先通过一个例子来了解一下这两个方法的基础用法,代码如下:public class Run { public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread();原创 2020-10-01 18:22:12 · 8959 阅读 · 0 评论 -
如何终止线程?
在 Java 中有三种方法可以使正在运行的线程终止:使用退出标志使线程正常退出。使用 interrupt() 方法终止线程。使用 stop() 方法强行终止线程,这种方法是过期作废的方法,使用它可能会发生不可预料的结果,不推荐使用。下面我将对这三种方法分别进行举例说明。一、使用退出标志在 run() 方法执行完毕后,线程就终止了,但是在某些特殊的情况下,run() 方法会被一直执行,此时就可以通过修改退出标志来结束 run() 方法,代码如下:public class Run {原创 2020-09-30 20:17:59 · 8803 阅读 · 0 评论 -
Thread 类部分常用方法详解
currentThread()currentThread() 方法用来返回代码段正在被哪个线程调用,它是 Thread 类提供的一个 native 方法,返回一个 Thread 类的实例对象,源码如下:public static native Thread currentThread();废话就不多说了,直接上代码:public class Run { public static void main(String[] args) { MyRunnable myRunnabl原创 2020-09-29 23:25:21 · 9850 阅读 · 0 评论 -
Java 实现多线程的四种方式
在 Java 中实现多线程一共有四种方式:继承 Thread 类实现 Runnable 接口实现 Callable 接口线程池下面我将对这四种方式进行入门级的解析和演示。一、继承 Thread 类通过继承 Thread 类实现多线程的步骤如下:创建 MyThread 类,让其继承 Thread 类并重写 run() 方法。创建 MyThread 类的实例对象,即创建一个新线程。调用 start() 方法,启动线程。代码示例如下:public class MyThread ex原创 2020-09-19 22:06:34 · 16623 阅读 · 0 评论 -
Java 多线程基础概念
什么是进程?进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。操作系统在运行一个程序时,会为其创建一个进程。什么是线程?线程与进程类似,但线程是一个比进程更小的执行单元,一个进程在执行过程中可以产生多个线程,线程是操作系统调度的最小单元。在 Java 中,同一进程的多个线程共享该进程的堆和方法区资源,但每个线程都有自己独立的程序计数器、虚拟机栈和本地方法栈,所以系统在线程之间切换工作的负担要比进程小,因此线程也被叫做轻量级进程。Java原创 2020-09-19 00:04:16 · 13536 阅读 · 0 评论