JUC & 多线程
文章平均质量分 94
JUC & 多线程
c&0xff00
纸上学来终觉浅
展开
-
SimpleDateFormat非线程安全解析
介绍SimpleDateFormat是JDK提供的rt包下的一个时间格式转换的类,它的全类名是:java.text.SimpleDateFormat。从该类的注释中,我们可以了解到:1、可以将date转为text格式2、可以将text转为date格式3、可以针对不同的时区进行转换4、允许你采用自定义的时间patter。(可以使用applyPattern方法来修改转换格式)他自己提供了一部分字母的含义,同时保留了’A’ to 'Z’和 ‘a’ to 'z’所有没有定义的字母,已提供的如下:原创 2021-03-03 12:32:42 · 367 阅读 · 1 评论 -
线程池ThreadPoolTaskExecutor使用不当的惨痛教训
问题现场:配置:生产环境nginx做负载均衡,后端三台服务器,这样一个传统的集群架构。现象:平时系统正常时,没怎么发现问题。最近随着业务量增大,我们以及依赖的一些第三方服务接连出现各种各样的服务超时,不可用的情况。最终我们也没有幸免,因为我们的业务依赖第三方接口的成分较大,属于一个用户接收,用户渠道的角色。这也就意味着如果第三方服务不可用,我们的相应服务也将不可用了。没错,最终我们的系统挂了!原因:原因是服务里面的一个接口不可用了,调用总是超时。而接口调用是在一个异步线程池中进行的。 <b原创 2020-11-26 09:28:50 · 13423 阅读 · 2 评论 -
LinkedBlockingQueue与ArrayBlockingQueue的区别
LinkedBlockingQueue看LinkedBlockingQueue之前可以参考前一篇:ArrayBlockingQueue源码解读例子将前面的例子改为LinkedBlockingQueue实现,我们看到,程序依然可以正常运行。package juc;import org.junit.Test;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingQueue;pu原创 2020-11-13 11:02:45 · 479 阅读 · 0 评论 -
ArrayBlockingQueue源码解读
ArrayBlockingQueue它是BlockingQueue阻塞队列基于数组的一种实现。阻塞队列:首先它是一个队列queue,同时如果队列为空,从队列取出元素的操作会被阻塞;如果队列为满,向队列中增加元素的操作会被阻塞。Queue的常见api辨析:boolean add(E e); // 向队列中增加元素,必须要加入进去。如果队列已满,抛出IllegalStateException异常boolean offer(E e);//本意是提供,意思是你要就拿走,不要告诉我一声。也是向队列增加元素原创 2020-11-13 08:58:23 · 240 阅读 · 0 评论 -
CyclicBarrier源码解读
CyclicBarrier本意是循环栅栏,顾名思义,它可以循环使用。它是一个同步辅助器,它允许一个或多个线程阻塞等待直到其他线程执行完一系列的操作之后到达一个共同的屏障再继续执行。有点类似百米跨栏,按时你每跨一个栏必须等待其他选手也到跨栏处。CountDownLatch与它有点类似,但CountDownLatch只能使用一次。可以参考:CountDownLatch源码解读CyclicBarrier的实现不再是基于AbstractQueuedSynchronizer,而是采用ReentrantLock与原创 2020-11-11 19:31:25 · 249 阅读 · 0 评论 -
CountDownLatch源码解读
CountDownLatch本意是倒数计时,它是一个线程同步的辅助工具。它允许一个或多个线程阻塞等待直到其他线程执行完一系列的操作之后再继续执行。几个主要的api:await()方法:阻塞等待,直到state等于0。(它是基于AbstractQueuedSynchronizer实现的)await(long timeout, TimeUnit unit):定时等待,直到state等于0或超时。countDown():将state减1,当state减到0之后,await阻塞的线程可以继续执行。说起原创 2020-11-11 17:15:19 · 196 阅读 · 0 评论 -
Semaphore源码解读
SemaphoreSemaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于AbstractQueuedSynchronizer。Semaphore的强大功能Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获取信号量。大小为n(n>0)的信号量可以实现限流的功能,它可以实现只能有n个线程同时获取信号量。光是以上的两个特性就能解决很多现实问题。代码示例import org.junit.Test;import java.u原创 2020-11-06 13:22:41 · 632 阅读 · 2 评论 -
尽量使用notifyAll,而不用notify
wait与notify,notifyAll他们都是Object类的方法,一般用在synchronized代码块中,用于当线程某个条件不满足时,通过wait()挂起线程,将线程加入到阻塞队列中。而当条件满足时,通过notify唤醒阻塞的线程,被唤醒的线程将会从wait()阻塞的位置继续执行。这里比较常用的格式是:while(条件不成立){ wait();}通过以上的方式,当线程被唤醒时,会继续判断条件是否成立。如果成立,则继续执行。notify与notifyAll的区别是:notify一次只唤原创 2020-11-05 14:28:36 · 575 阅读 · 1 评论 -
JAVA内存模型(Happens-Before 规则)
JAVA内存模型由来1、cpu多核缓存会带来数据的可见性问题2、编译优化会带来机器指令的有序性问题前面这两个问题是计算机科学,硬件发展衍生出来的。在提高性能的同时,也引发出对并发编程(共享变量)的一些问题。解决可见性问题最简单的思路是禁用cpu缓存,每次读数据从内存中读取,写数据后就及时刷新到内存中。解决有序性问题最简单的思路是禁用指令重排序。说白了就是放弃了计算机发展带来的便利,势必会造成性能的大幅下降。可是我们又要保证程序正确,没有并发问题,那我们可以按需禁用,只在存在并发问题的数据上禁原创 2020-11-04 09:01:46 · 354 阅读 · 1 评论 -
ReentrantLock源码解读(condition原理)
回顾ReentrantLock源码解读(lock、unlock原理)前面我们看了ReentrantLock的加锁解锁原理,明白了ReentrantLock通过AbstractQueuedSynchronizer实现了保护临界区的功能。让一个线程尝试去获取锁的时候,如果当前锁已经被其他线程占用,那么该线程就会阻塞,加入到阻塞队列中。直到持有锁的线程调用unlock,释放锁之后才会从阻塞队列中唤醒一个线程进入临界区。阻塞队列不止一个上面我们提到,如果所以被其他线程占用,尝试加锁的线程将会被加入到阻塞队列原创 2020-11-01 19:54:22 · 720 阅读 · 2 评论 -
ReentrantLock源码解读(lock、unlock原理)
ReentrantLock简介ReentrantLock是JDK中JUC包下的工具类,顾名思义,它是可重入的,同一个线程可以多次获取锁。借助它可以实现只有一个线程同时访问临界区。推荐的使用方式: * class X { * private final ReentrantLock lock = new ReentrantLock(); * // ... * public void m() { * lock.lock(); // block until condition h原创 2020-10-30 19:27:17 · 314 阅读 · 0 评论 -
线程的两阶段终止模式(中断)
Java 中线程的生命周期Java 语言中线程共有六种状态,分别是:1、NEW(初始化状态)2、RUNNABLE(可运行 / 运行状态)3、BLOCKED(阻塞状态)4、WAITING(无时限等待)5、TIMED_WAITING(有时限等待)6、TERMINATED(终止状态)他们之间的关系转换如以下状态转换图:TERMINATED(终止状态)今天主要讲线程如何从Runnable状态如何变为终止状态。第一种:线程的任务执行完了,就进入了terminated状态。(这个好理解,我们原创 2020-10-30 09:14:12 · 680 阅读 · 0 评论 -
java多线程总结 - 基础篇
进程与线程区别进程是内存分配的最小单位,进程中会有多个线程。引入线程的目的是因为计算机cpu上下文切换会很频繁,而进程的上下文切换相对耗时耗资源。而线程是在进程中的,是cpu分配的最小单位,进程中的多个线程共享一块内存。线程的上下文切换成本更低。线程的状态New、Runable、Running、Blocked、Dead线程的start与run方法的区别start:新创建一个线程并执行run方法run:在当前线程执行run方法start方法源码:/** * Causes this原创 2020-09-21 09:33:29 · 110 阅读 · 0 评论 -
Synchronized与Lock的区别 总结
面试官问:Synchronized与Lock的有什么区别?表层区别:他们都可以解决线程同步的问题,synchronized是关键字,Lock是JUC下的接口。实现方式:synchronized可以锁类、锁对象、锁方法,是JVM级别的,比如锁对象的情况,对象头上会有锁标志,以及等待执行的线程队列。Lock是用户态的,比如ReentrantLock、ReentrantReadWriteLock是通过AQS,基于信号量以及CAS实现的,性能相对较高。在JDK6之前,synchronized被.原创 2020-06-17 19:34:47 · 341 阅读 · 0 评论 -
通过管程和信号量分别实现生产者消费者模式
了解管程管程是操作系统中的一个概念,在操作系统中,当多个进程或线程方法共享变量(俗称临界区)的时候,我们需要控制同一时刻只能有一个线程对共享变量进行访问。其中一种方案是通过互斥量实现,比如锁、信号量,该种方案需要程序员在访问临界区前手动加锁,结束访问后释放锁,增加了编码难度和错误率。管程将要访问的共享变量、访问变量的过程、数据结构 封装起来,程序员只要调用管程就可以实现线程同步,同步的操作管程已经给你做好了。了解生产者消费者模式在现实生活中,总是有生产消费的问题,比如我给你写一封邮件,我就是原创 2020-05-24 19:38:40 · 502 阅读 · 0 评论 -
Executors创建线程池会造成OOM问题
看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,通过源码分析禁用的原因写在前面首先感谢大家阅读本篇文章,通过阅读本篇文章你将了解到: 线程池的定义 Executors创建线程池的几种方式 ThreadPoolExecutor对象 线程池执行任务逻辑和线程池参数的关系...转载 2020-02-25 09:12:50 · 8810 阅读 · 5 评论