Thread
文章平均质量分 88
JFS_Study
IP属地以运营商信息为准,境内显示到省(区、市),境外显示到国家(地区)
展开
-
ForkJoin 线程池
一、分而治之严格来讲,分而治之不算一种模式,而是一种思想。它可以将一个大任务拆解为若干个小任务并行执行,提高系统吞吐量。主要讲两个场景,Master-Worker 模式,ForkJoin 线程池。ForkJoin 线程池是 jdk7 之后引入的一个并行执行任务的框架,其核心思想也是将任务分割为子任务,有可能子任务还是很大,还需要进一步拆解,最终得到足够小的任务。将分割出来的子任务放入双端队列中,然后几个启动线程从双端队列中获取任务执行。子任务执行的结果放到一个队列里,另起线程从队列中获取数据,合并结果。原创 2022-01-18 10:09:41 · 995 阅读 · 0 评论 -
Java 对象头:理解锁升级
一、简述在 JVM 中,对象在堆内存中的布局分为三块区域:对象头、实例变量和填充数据。1️⃣【对象头区域】Java对象的对象头由 mark word 和 class pointer 两部分组成。对象自身的运行时数据(MarkWord)。存储 hashcode、GC 分代年龄、锁类型标记、偏向锁线程 ID、CAS 锁指向线程 LockRecord 的指针等,synchronized 锁的机制与这个部分(markwork)密切相关,用 markword 中最低的三位代表锁的状态,其中一位是偏向锁位原创 2022-01-12 16:26:53 · 805 阅读 · 0 评论 -
理解阿里不允许用Executors去创建线程池
一、简述阿里开发手册关于多线程的一段描述:线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式。这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。Executors 返回的线程池对象的弊端如下:1️⃣FixedThreadPool 和 SingleThreadPool允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。原因很简单:newSingleThreadExecutor 和 newF原创 2021-07-02 10:17:02 · 404 阅读 · 0 评论 -
原子操作类AtomicInteger
一、Java 自增/自减是非线程安全的对于 Java 中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的。num++解析为num=num+1,该操作不具备原子性,多线程并发共享这个变量时必然会出现问题。测试:public class AtomicIntegerTest { private static final int THREADS_CONUT = 20; public static int count = 0; public static原创 2021-07-02 10:12:18 · 166 阅读 · 0 评论 -
StringBuilder 线程不安全的两个原因
一、简述StringBuilder 和 StringBuffer 的内部实现跟 String 一样,都是通过 char[] 存储字符串。不同的是 String 里面的 char[] 是 final 修饰的,是不可变的,而 StringBuilder 和 StringBuffer 的 char[] 是可变的。StringBuilder 不是线程安全的,StringBuffer 是线程安全的。看一下多线程操作 StringBuilder 对象会出现什么问题:public static void main(S原创 2021-07-02 10:09:43 · 1477 阅读 · 0 评论 -
线程池里有几个线程在运行
一、问题假设有一个线程池,核心线程数为 10,最大线程数也为 20,任务队列为 100。现在来了 100 个任务,线程池里现在有几个线程运行?正确的答案是“不一定”!因为并没指明是哪一种线程池机制。二、解答1️⃣先进队列,到最大值,再起线程这种最容易被想到,因为 JDK 中的线程池,也就是 ThreadPoolExecutor 就是这种机制的!ThreadPoolExecutor 的 execute(Runnable command) 如下:public void execute(Runnable原创 2021-07-02 10:07:33 · 1194 阅读 · 0 评论 -
for update
一、for update定义for update 是一种行级锁,又叫排他锁。一旦用户对某个行施加了行级锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行。如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁。即使多个用户对一个表均使用了共享更新,但也不允许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。只有当出现如下之一的条件,才会释放共享更新锁:1、执行提交(COMMIT)语句2、退出数据原创 2021-07-02 10:03:30 · 310 阅读 · 0 评论 -
进程之间的8种通信方式
进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。IPC 的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、套接字Socket、Streams等。其中 Socket 和 Streams 支持不同主机上的两个进程IPC。一、无名管道(pipe)管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。二、高级管道(popen)将另一个程序当做一个新的进程在当前程序原创 2021-07-01 17:11:54 · 1154 阅读 · 0 评论 -
ReentrantLock 可重入锁的使用
何为可重入锁?当一个线程获得了当前实例的锁,并进入方法 a,这个线程在没有释放这把锁的时候,可以再次进入方法 a。Synchronized和Lock区别一、简介Java 除了使用关键字 synchronized 外,还可以使用 ReentrantLockLock的一个实现类实现排他锁(Exclusive Locks)的功能。而且 ReentrantLock 比 synchronized 功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。#二、使用1️⃣简单使用:一个最基础的使用案例,也就是实原创 2021-07-01 17:10:41 · 491 阅读 · 0 评论 -
synchronized 和 Lock 的区别
在分布式开发中,锁是线程控制的重要途径。Java 为此提供了两种锁机制,synchronized 和 lock。ReentrantLock 在内存上的语义与 synchronized 相同,但是它提供了额外的功能,可以作为一种高级工具。当需要一些可定时,可轮询,可中断的锁获取操作,或者希望使用公平锁,或者使用非块结构的编码时才应该考虑 ReetrantLock。在业务并发简单清晰的情况下推荐 synchronized,在业务逻辑并发复杂,或对使用锁的扩展性要求较高时,推荐使用 ReentrantLock 这原创 2021-07-01 17:08:32 · 1764 阅读 · 0 评论 -
MySQL乐观锁电商库存并发问题应用
一、案例说明银行两操作员(甲/乙)同时操作同一账户。两人同时读取一余额为 1000 元的账户,甲为该账户增加 100 元,乙同时为该账户扣除 50 元,甲先提交,乙后提交。最后实际账户余额为 1000-50=950,但本该为 1000+100-50=1050。这就是典型的并发问题。乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实原创 2021-07-01 17:05:40 · 185 阅读 · 0 评论 -
进程线程、同步异步、阻塞非阻塞、并发并行
一、进程和线程1️⃣【进程Process】是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。2️⃣【线程Thread】是进程中的基原创 2021-07-01 17:02:54 · 477 阅读 · 0 评论 -
java.util.concurrent包下的并发容器
一、简述不考虑多线程并发的情况下,容器类一般使用ArrayList、HashMap等线程不安全的类,效率更高。并发场景,常用到ConcurrentHashMap、ArrayBlockingQueue等线程安全的容器类,虽然牺牲了一些效率,但却得到了安全。#二、java.util.concurrent包下的线程安全容器ConcurrentHashMap:并发版HashMapCopyOnWriteArrayList:并发版ArrayListCopyOnWriteArraySet:并发SetConc原创 2021-07-01 16:59:38 · 334 阅读 · 0 评论 -
Java多线程优化
一、Java 系统内部锁优化当使用 Java 多线程访问共享资源的时候,会出现竞态的现象。即随着时间的变化,多线程“写”共享资源的最终结果会有所不同。为了解决这个问题,让多线程“写”资源的时候有先后顺序,引入了锁的概念。每次一个线程只能持有一个锁进行写操作,其它线程等待该线程释放锁以后才能进行后续操作。从这个角度来看,锁的使用在 Java 多线程编程中是相当重要的,那么是如何对锁进行优化?Java 的锁分为两种:一种是内部锁,它用 Synchronized 关键字来修饰,由 JVM 负责管理,并且不会出原创 2021-07-01 16:55:34 · 973 阅读 · 0 评论 -
Spring中@Async
一、简述在 Java 应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务。其实,在 Spring3.x 之后,就已经内置了 @Async 来完美解决这个问题。二、何为异步调用在解释异步调用之前,先来看同步调用的定义:同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕,而是继续执行下面的流程。例如,在某个调用中,原创 2021-07-01 16:53:05 · 142 阅读 · 0 评论 -
线程通信的几种方式
一、问题有两个线程,A 线程向一个集合里面依次添加元素“abc”字符串,一共添加十次,当添加到第五次的时候,希望 B 线程能够收到 A 线程的通知,然后 B 线程执行相关的业务操作。线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。二、使用 volatile 关键字基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想。大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式public原创 2021-07-01 16:50:36 · 22725 阅读 · 6 评论 -
如何确保三个线程顺序执行
三个线程t1、t2、t3。确保三个线程,t1 执行完后 t2 执行,t2 执行完后 t3 执行。一、使用 CountDownLatch二、使用 jointhread.join 把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程 A 中调用了线程 B 的 join(),直到线程 B 执行完毕后,才会继续执行线程 A。public class ThreadTest1 { // T1、T2、T3三个线程顺序执行 public static void main(Stri原创 2021-07-01 16:47:24 · 2334 阅读 · 0 评论 -
ForkJoin线程池
一、分而治之严格来讲,分而治之不算一种模式,而是一种思想。它可以将一个大任务拆解为若干个小任务并行执行,提高系统吞吐量。主要讲两个场景,Master-Worker 模式,ForkJoin 线程池。ForkJoin 线程池是 jdk7 之后引入的一个并行执行任务的框架,其核心思想也是将任务分割为子任务,有可能子任务还是很大,还需要进一步拆解,最终得到足够小的任务。将分割出来的子任务放入双端队列中,然后几个启动线程从双端队列中获取任务执行。子任务执行的结果放到一个队列里,另起线程从队列中获取数据,合并结果。原创 2021-07-04 00:02:41 · 311 阅读 · 2 评论 -
同步问题的解决--锁对象Lock
Synchronized和lock区别一、java.util.concurrent.locksLock 是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题。代码如下:public class LockTest { public static void main(String[] args) { final Outputter op = new原创 2021-06-30 11:14:35 · 314 阅读 · 0 评论 -
SimpleDateFormat的线程安全问题与解决
SimpleDateFormat的线程安全问题与解决原创 2021-06-30 11:11:40 · 255 阅读 · 0 评论 -
线程的控制方法
一、Java 中的线程状态转换【注】不是 start 之后就立刻开始执行,只是就绪了(CPU 可能正在运行其他的线程)。只有被 CPU 调度之后,线程才开始执行,当 CPU 分配给的时间片到了,又回到就绪状态,继续排队等候。二、线程控制的基本方法isAlive():判断线程是否还活着。start 之后,终止之前都是活的。getPriority():获得线程的优先级数值。setPriority():设置线程的优先级数值(线程是有优先级别的)。Thread.sleep():将当前线程睡眠指定.原创 2021-06-30 11:10:00 · 1910 阅读 · 1 评论 -
同步计数器 CountDownLatch(闭锁)
一、概念CountDownLatch 是java.util.concurrent中的一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是互斥)的作用。机制是只要提供的多个(具体数量等于初始化CountDownLatch时count的值)线程都达到了预期状态或者完成了预期工作时触发事件,其他线程可以等待这个事件来触发自己后续的工作。等待的线程可以是多个,即 CountDownLatch 可以唤醒多个等待的线程。到达自己预期状态的线程会调用 CountDownLatch 的 count原创 2021-06-30 11:06:05 · 504 阅读 · 0 评论 -
ThreadLocal 的原理及用法
一、ThreadLocal原理简单说 ThreadLocal 就是一种以空间换时间的做法,在每个 Thread 里面维护了一个以开放定址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了。JDK1.2 就提供了java.lang.ThreadLocal。ThreadLocal 为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal 并不是一个 Thread,而是 Thre原创 2021-06-30 11:04:34 · 1275 阅读 · 0 评论 -
线程安全:内存的安全
如果代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么代码就是线程安全的。一、简述tip:既要保证线程安全又要尽可能提升性能,怎么取得平衡1️⃣分析业务场景,尽可能的实现无锁编程。2️⃣对于并发场景,尽可能的缩小锁的范围。论语中有句话叫“学而优则仕”,相信很多人都觉得是“学习好了可以做官”。然而,这样理解却是错的,切忌望文生义。同理,“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个原创 2021-06-30 11:01:40 · 462 阅读 · 0 评论 -
AbstractQueuedSynchronizer(AQS)
AbstractQueuedSynchronizer(AQS)原创 2021-06-30 10:59:57 · 333 阅读 · 0 评论 -
Java多线程那点事儿
一、CyclicBarrier 和 CountDownLatch 的区别两个看上去有点像的类,都在java.util.concurrent下,都可以用来表示代码运行到某个点上,二者的区别在于:1️⃣CyclicBarrier 的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这个点,所有线程才重新运行;CountDownLatch 则不是,某线程运行到某个点上之后,只是给某个数值 -1 而已,该线程继续运行。2️⃣CyclicBarrier 只能唤起一个任务,CountDownLa原创 2021-06-30 10:57:43 · 119 阅读 · 0 评论 -
多线程死锁的产生以及如何避免死锁
多线程死锁的产生以及如何避免死锁原创 2021-06-30 10:53:29 · 1403 阅读 · 0 评论 -
ThreadPoolTaskExecutor
一、线程池配置方式ThreadPoolTaskExecutor 是 Spring 的线程池技术,利用它可以轻松的实现线程池。具体可参照 ThreadPoolExecutor。1️⃣xml 配置方式pom.xml:<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactI原创 2021-06-30 10:39:29 · 255 阅读 · 0 评论 -
【线程通信】生产者-消费者模式
一、简述1️⃣生产者消费者模式并不是 GOF 提出的 23 种设计模式之一,23 种设计模式都是建立在面向对象的基础之上的,但其实面向过程的编程中也有很多高效的编程模式,生产者消费者模式便是其中之一,它是编程过程中最常用的一种设计模式。一个常见的场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。单单抽象出生产者和消费者,还够不上是生产者/消费者模式。该模式还需要有一个缓冲区处原创 2021-05-06 15:10:10 · 721 阅读 · 0 评论 -
Java线程的四种创建方式及五种状态
一、多线程的作用1️⃣发挥多核 CPU 的优势随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至 16 核的也不少见。如果是单线程的程序,那么在双核 CPU 上就浪费了50%,在 4 核 CPU 上就浪费了 75%。单核 CPU 上所谓的“多线程”是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程“同时”运行罢了。多核 CPU 上的多线程才是真正的多线程,它能让多段逻辑同时工作。多线程,可以真正发挥出多核 CPU 的优势来,达到原创 2021-05-06 15:02:42 · 2480 阅读 · 0 评论 -
Java线程池
一、简述为避免频繁地创建和销毁线程,达到线程对象的重用,因而使用线程池。另外,使用线程池还可以根据项目灵活地控制并发的数目。1️⃣线程池的概念线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果线程池所有线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时原创 2021-05-06 14:53:00 · 150 阅读 · 0 评论 -
synchronized
Synchronized和Lock的区别ReentrantLock可重入锁的使用一、简述synchronized 关键字是一把经典的 JVM 级别的锁。在加了它的方法、代码块中,一次只允许一个线程进入特定代码段,从而避免多线程同时修改同一数据。在 jdk1.6 之前,syncronized 是一把重量级的锁,不过随着 jdk 的升级,也在对它进行不断的优化,如今它变得不那么重了,甚至在某些场景下,它的性能反而优于轻量级锁。实现原理就是锁升级的过程。1️⃣synchronized的作用原子性:保证原创 2021-05-04 13:45:59 · 654 阅读 · 0 评论 -
Java线程池ThreadPoolExecutor类
一、简述在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面使得线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。线程池不允许使用 Executors 去创建,而要通过 ThreadPoolExecutor 方式,这一方面是由于 jdk 中 Executor 框架虽然提供了如 newFixedThreadPool()、newSingleThreadExecutor()、newCachedTh.原创 2021-05-04 12:47:47 · 485 阅读 · 0 评论 -
什么是乐观锁,什么是悲观锁
一、并发控制当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。这种手段就叫做并发控制。并发控制的目的是保证一个用户的工作不会对另一个用户的工作产生不合理的影响。没有做好并发控制,就可能导致脏读、幻读和不可重复读等问题。常说的并发控制,一般都和数据库管理系统(DBMS)有关。在 DBMS 中的并发控制的任务,是确保在多个事务同时存取数据库中同一数据时,不破坏事务的隔离性、一致性和数据库的统一性。实现并发控原创 2021-05-04 12:44:41 · 319 阅读 · 0 评论