java多线程
文章平均质量分 65
静看星辰变
我要成为像凯撒一样的男人
展开
-
【多、单】生产者消费者模式——Java
实现代码下面是多生产者多消费者的实现,import java.util.ArrayDeque;import java.util.Deque;/**生产者、消费者。单生产者、消费者,多生产者消费者。要注意以下三点: * 如果队列为空,则消费者阻塞 * 如果队列满了,则生产者阻塞 * 任何时候,只能有一个生产者或者消费者访问队列 * @author zkw * @date 2021/1/4 10:07 */public class ProducerAn原创 2021-01-04 11:54:49 · 882 阅读 · 0 评论 -
【Java多线程】Java8 ConcurrentHashMap
Java7 中实现的 ConcurrentHashMap 说实话还是比较复杂的,Java8 对 ConcurrentHashMap 进行了比较大的改动。建议读者可以参考 Java8 中 HashMap 相对于 Java7 HashMap 的改动,对于 ConcurrentHashMap,Java8 也引入了红黑树。说实话,Java8 ConcurrentHashMap 源码真心不简单,最难的在...转载 2020-04-13 19:42:34 · 226 阅读 · 0 评论 -
【JUC阻塞队列】ConcurrentLinkedQueue
目录1 前言2 队列结构3 入队——offer()方法3.1 入队过程3.2 offer()源码3.3 tail并非一直指向尾结点的意图4 出队——poll()方法4.1 出队过程4.2 poll()源码5 其它方法5.1 size()1 前言本人jdk版本1.8。在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两种方式...原创 2020-04-07 15:42:23 · 527 阅读 · 0 评论 -
【操作系统】死锁的原因、必要条件、检测、预防、解除
1 前言所谓死锁(Deadlock),是指多个进程在运行过程中因争夺资源而造成的一种僵局(DeadlyEmbrace),当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进,同时它们所占用的cpu、内存等资源也得不到释放。2 死锁产生的原因2.1 竞争资源引起进程死锁非剥夺性资源,当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机...原创 2020-04-06 20:04:06 · 2000 阅读 · 0 评论 -
【JUC阻塞队列】ArrayBlockingQueue和LinkedBlockingQueue
目录Java中的阻塞队列1ArrayBlockingQueue1.1 成员变量1.2 构造方法1.3 put方法1.4 take方法2LinkedBlockingQueue2.1 成员变量2.2 构造方法2.3 put方法2.4 take方法3ArrayBlockingQueue和LinkedBlockingQueue的区别Java中的阻塞...原创 2020-03-26 22:28:58 · 522 阅读 · 0 评论 -
【Java多线程】wait()和join()被中断的过程
开启两个线程,一个线程等待,另一个线程获取锁后打印信息,打印期间对等待线程进行中断,通过打印的控制台信息来查看中断过程。public class Test3 { static Object lock = new Object(); // 同步锁和等待锁 public static void main(String[] args) throws Interrupte...原创 2020-03-25 20:18:46 · 1568 阅读 · 3 评论 -
【Java多线程】原子操作实现之CAS
目录1 前言2 CAS机制3 CAS实现原子操作的弊端3.1ABA问题3.2 循环时间长开销大3.3 只能保证一个共享变量的原子操作1 前言Java中除了使用锁来实现原子操作外,还大量的使用了CAS机制来实现对共享资源的原子操作。从JDK1.5版本开始,JDK的并发包中提供了以Atomic开头的类,来支持原子操作,比如AtomicBoolean,AtomicInt...原创 2020-03-25 19:00:43 · 151 阅读 · 0 评论 -
【Java多线程实战设计】如何实现一个并发安全的链表
1 思路对于链表这类的数据结构,无非就涉及到增删改查四种基本操作,我们只要保证在对链表进行增删改查时是线程安全的即可。在绝大多数情况下,读的操作多于增删改的操作,所以可以考虑使用JUC包下的读写锁类ReentrantReadWriteLock,当进行读操作时获取读锁,进行增删改操作时获取写锁。这样可以保证多个线程可以同时读取链表中的数据,某个时刻只有一个线程能对链表进行增删改。Reentran...原创 2020-03-23 09:53:38 · 2273 阅读 · 1 评论 -
【Java多线程实战设计】用三个线程按顺序循环打印abc三个字母,比如abcabcabc
目录1 思路2 synchronized/wait/notifyAll 机制3 ReentrantLock/Condition.await()/Condition.signalAll() 机制1 思路启动三个线程,采用多线程间等待/通知的机制来设计。维护一个全局不变数组printArr和变量索引index,printArr[index]就是接下来的线程要打印的字符。三个线程一开...原创 2020-03-21 21:31:15 · 829 阅读 · 0 评论 -
【Java并发工具】Semaphore
目录1 前言2 应用场景3 其它方法4 实现原理4.1 实现的同步器4.2 执行过程1 前言本人使用jdk8版本。Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。举个例子,比如××马路要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须在路口等待,所以前一百辆车会看到绿灯,可以开进这条马...原创 2020-03-21 15:04:15 · 309 阅读 · 0 评论 -
【Java并发工具】CyclicBarrier
目录1 前言2 示例3 实现原理3.1 成员变量3.2 构造方法3.3 await方法3.4 reset方法4CyclicBarrier和CountDownLatch的区别1 前言本人使用jdk8版本。CyclicBarrier的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻...原创 2020-03-20 23:13:57 · 174 阅读 · 0 评论 -
【Java并发工具】CountDownLatch
1 前言本人使用jdk8版本。CountDownLatch允许一个或多个线程等待其他线程完成操作,作用与Thread.join()相似,join可以参考:Thread.join()原理。2 功能介绍在JDK 1.5之后的并发包中提供的CountDownLatch也可以实现join的功能,并且比join的功能更多,示例如下:public class CountDown...原创 2020-03-20 22:01:56 · 136 阅读 · 1 评论 -
操作系统与Java中线程的生命周期和线程状态
1 操作系统中的线程状态创建:线程从创建到被cpu执行之前的这个阶段。 就绪:指线程已具备各种执行条件,一旦获取cpu便可执行。 运行:表示线程正获得cpu在运行。 阻塞:指线程在执行中因某件事而受阻,处于暂停执行的状态,阻塞的线程不会去竞争cpu。 终止:线程执行完毕,接下来会释放线程占用的资源。线程的生命周期图如下(进程与线程生命周期一样):2 Java中线程的状态T............原创 2020-03-18 23:11:08 · 1037 阅读 · 4 评论 -
【Java多线程】Thread.join()原理
1 前言如果一个线程A执行了Thread.join()方法,含义是,当前线程A等待Thread线程终止之后才从Thread.join()返回。线程Thread除了Thread.join(),还有Thread.join(long millis)和Thread.join(long millis, int nanos)两个具备超时特性的方法。表示如果线程thrad在给定时间内没有终止,那么将会从超时...原创 2020-03-16 21:47:00 · 827 阅读 · 0 评论 -
Atomic原子类及原理
一、引入 原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作是原子操作。再比如:a++;这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。 但是,像i++这种非原子操...原创 2020-03-16 10:57:33 · 5324 阅读 · 0 评论 -
【Executor框架】FutureTask——jdk1.8
目录1 前言2 在Executor框架中的使用3FutureTask原理3.1 运行状态3.2 等待队列4 get方法(未完成则线程阻塞)5 run方法(完成则唤醒阻塞线程去获取结果)1 前言本人jdk版本8Future接口和实现Future接口的FutureTask类,代表异步计算的结果。FutureTask除了实现Future接口外,还实现了Runna...原创 2020-03-15 16:14:02 · 308 阅读 · 1 评论 -
【Executor框架】ScheduledThreadPoolExecutor详解——基于jdk1.8
1 前言本人使用的jdk版本为8。原创 2020-03-14 23:17:37 · 555 阅读 · 0 评论 -
【Java并发锁】Condition接口——等待/通知工具
目录1 Object监视器方法与Condition接口比较2 Condition接口与示例3 Condition实例4 Condition的实现分析4.1等待队列4.2等待4.3 通知本人使用jdk8版本。1 Object监视器方法与Condition接口比较任意一个Java对象,都拥有一组监视器方法,定义在java.lang.Object中,主要包括w...原创 2020-03-14 20:05:01 · 413 阅读 · 0 评论 -
【Executor框架】ThreadPoolExecutor详解(3种ThreadPool)
Executor框架最核心的类是ThreadPoolExecutor,它是线程池的实现类,主要由下列4个组件构成。corePool:核心线程池的大小。 maximumPool:最大线程池的大小。 BlockingQueue:用来暂时保存任务的工作队列。 RejectedExecutionHandler:当ThreadPoolExecutor已经关闭或ThreadPoolExecutor已...原创 2020-03-14 14:59:05 · 339 阅读 · 0 评论 -
【Executor框架】简介——两级调度模型、结构、框架主要成员
1 前言在Java中,使用线程来异步执行任务。Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源。同时,为每一个任务创建一个新线程来执行,这种策略可能会使处于高负荷状态的应用最终崩溃。Java的线程既是工作单元,也是执行机制,线程中定义的run方法即是工作单元的内容,线程最后调用自己的start()来执行自己。从JD...原创 2020-03-10 16:27:02 · 685 阅读 · 0 评论 -
【Executor框架】Java中的线程池(ThreadPoolExecutor实现原理、使用、状态维护)
目录1 为什么使用线程池2 线程池的实现原理3 线程池的使用3.1 线程池的创建3.2 向线程池提交任务3.3 关闭线程池3.4 合理的配置线程池3.5 线程池的监控1 为什么使用线程池在开发过程中,合理地使用线程池能够带来3个好处。降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 提高响应速度。当任务到达时,任务可以不需要等到线程...原创 2020-03-09 23:02:10 · 469 阅读 · 0 评论 -
【Java并发锁】ReentrantLock可重入锁
1 前言本人使用jdk8版本。原创 2020-03-09 22:14:57 · 96 阅读 · 0 评论 -
【Java并发锁】AbstractQueuedSynchronizer共享式同步状态获取与释放
1 前言本人使用jdk8版本。共享式获取与独占式获取最主要的区别在于同一时刻能否有多个线程同时获取到同步状态。以文件的读写为例,如果一个程序对该文件进行读操作,那么这一时刻对于该文件的写操作均被阻塞,而读操作能够同时进行。写操作要求对资源的独占式访问,而读操作可以是共享式访问,两种不同的访问模式在同一时刻对文件或者资源的访问情况。左半部分共享式访问资源时,其他共享式的访问均被允许,...原创 2020-03-08 21:50:15 · 357 阅读 · 1 评论 -
【Java并发锁】ReentrantReadWriteLock读写锁
1 前言本人使用jdk8版本读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞。读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。 一般情况下,读写锁的性能都会比排它锁好,因为大多数场景读多于写的,在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量。java并发包提供读写锁的实现是R...原创 2020-03-08 20:53:19 · 423 阅读 · 0 评论 -
Java偏向锁/轻量级锁/重量级锁及锁的升级
1 前言在Java SE1.6之前,synchronized一直都是重量级锁,如果某个线程获得了锁,其它获取锁的线程必须阻塞。在高并发的情况下,会有大量线程阻塞,导致系统响应速度急剧下降;同时不断的获取和释放锁也会导致线程不断切换,给系统造成较大的负担。在Java SE1.6之后,为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。这些锁就存在锁对象的对象...原创 2020-03-06 17:15:26 · 750 阅读 · 1 评论 -
Synchronized与Java对象头
1 synchronized实现原理synchronized实现同步的基础是:Java中的每一个对象都可以作为锁。具体表现为以下3种形式:对于普通同步方法,锁是当前实例对象。 对于静态同步方法,锁是当前类的Class对象。 对于同步方法块,锁是Synchonized括号里配置的对象。当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。那么锁到底存在哪里呢?锁...原创 2020-03-06 12:47:53 · 394 阅读 · 0 评论 -
Java中各种锁介绍
乐观锁、悲观锁,可重入锁,共享锁、独占锁转载 2020-03-05 23:39:38 · 149 阅读 · 0 评论 -
【Java并发锁】AbstractQueuedSynchronizer独占式同步状态获取与释放
前言本人使用jdk8版本。通过调用同步器的acqurie(int arg)方法可以获取同步状态,该方法对中断不敏感,也就是由于线程获取同步状态失败后进入同步队列,后续对线程进行中断操作时,线程也不会从同步队列中移出。同步器中使用acquire()和release()来获取和释放锁,这两个方法主要是调用的实现锁中重写的tryAcquire()和tryRelease()。这里提前说明,tr...原创 2020-03-04 20:29:40 · 387 阅读 · 0 评论 -
【Java并发锁】AbstractQueuedSynchronizer队列实现
同步器是依赖于内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态是释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。同步对列中的节点(Node)用来保存获取同步状态失败的线程引用、等待状态以及前驱和后继节点,节点的属性类型与名称以及描述:...原创 2020-03-03 21:16:15 · 145 阅读 · 0 评论 -
【Java并发锁】AbstractQueuedSynchronizer接口与示例
1 前言本人jdk版本8。队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作,并发包的作者(doug Lea)期望他能够称为实现大部分同步需求的基础。同步器是实现锁(也可以是任意同步组件)的关键,在锁的实现中聚合同步器,利用...原创 2020-03-03 20:51:16 · 120 阅读 · 0 评论 -
【Java并发锁】Lock
1 前言在Lock接口出现之前,java程序靠的是synchronized关键字实现共享锁功能的,而Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能。Concurrent包中已经提供的实现了Lock接口的锁包括:ReentrantLock(可冲入锁)和ReadWriteLock(读写锁)等。它提供了synchronized关键字类似的同步功能,只是在使用是...原创 2020-03-03 19:59:02 · 166 阅读 · 0 评论 -
CLH锁
CLH是一种基于单向链表的高性能、公平的自旋锁。申请加锁的线程通过前驱节点的变量进行自旋。在前置节点解锁后,当前节点会结束自旋,并进行加锁。基于线程当前节点的前置节点的锁值(locked)进行自旋,locked == true 自旋,locked == false 加锁成功。 locked == true 表示节点处于加锁状态或者等待加锁状态。 locked == false 表示节点处于...转载 2020-03-02 21:56:04 · 200 阅读 · 0 评论 -
Doug Lea并发编程文章全部译文
Doug Lea并发编程文章全部译文如果IT的历史,是以人为主体串接起来的话,那么肯定少不了Doug Lea。这个鼻梁挂着眼镜,留着德王威廉二世的胡子,脸上永远挂着谦逊腼腆笑容,服务于纽约州立大学Oswego分校计算机科学系的老大爷。说他是这个世界上对Java影响力最大的个人,一点也不为过。因为两次Java历史上的大变革,他都间接或直接的扮演了举足轻重的角色。一次是由JDK 1.1到JDK...转载 2020-02-26 16:42:25 · 314 阅读 · 0 评论 -
【Java多线程】Java中断机制
前提假设程序需要停止正在运行的线程,如果直接stop线程,则有可能导致程序运行不完整、造成数据的不一致性以及其它不可控情况,因此Java提供了中断机制。何为中断每个线程都有一个与之相关联的 Boolean 属性,用于表示线程的中断状态(interrupted status)。中断状态初始时为 false。当另一个线程通过调用Thread.interrupt()中断一个线程时,会出现...原创 2020-02-25 14:26:06 · 565 阅读 · 0 评论 -
同步方法与同步代码块的效率比较
在《java并发编程实战》中提到同步方法在并发量大的情况下效率很低,但是为了保证程序的安全性,采用同步锁又是不得不考虑的问题,那有没有办法做到安全性和高效率同时实现呢?书中提到了可以用同步代码块取代对整个方法的同步,仅对方法中操作共享变量的代码加同步锁,这样就能使没有获取到锁的线程能执行同步代码块之前的代码,进而提高程序性能。1 代码介绍这里采用一个因式分解的例子,用户请求传入一个int数...原创 2020-01-06 16:02:44 · 1339 阅读 · 0 评论 -
synchronized关键字的继承
子类同步方法的同步性今天看到synchronized关键字的内容,讲到了当子类继承有同步方法的父类时,继承过来的方法是否仍然是同步的?当然,提到方法继承就必须提到方法重写,重写过后的方法是否仍然具有同步性,我找了一些别人的检测代码。下面是一个父类Super和3个子类(Sub1、Sub2、Sub3),不要看着代码很多,其实同步方法里面只有sleep方法和一些日志打印。这里列出了三种情况,来检...原创 2020-01-03 16:42:06 · 478 阅读 · 0 评论 -
【Java虚拟机】指令重排序
定义指令重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。即只要程序的最终结果与它顺序化情况的结果相等,那么指令的执行顺序可以与代码逻辑顺序不一致,这个过程就叫做指令的重排序。指令重排序的意义:使指令更加符合CPU的执行特性,最大限度的发挥机器的性能,提高程序的执行效率。数据依赖性如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间...原创 2020-01-03 09:09:02 · 584 阅读 · 0 评论 -
volatile特性详解
volatile变量对所有线程是立即可见的包含两个意思:对一个volatile变量的读总是能看到任意线程对这个变量最后的写,即每次读取volatile变量的时候,会使线程工作内存中的变量副本无效,从而必须从主内存中更新变量值。 对一个volatile变量进行写操作后,会立刻将修改的值同步到主内存,以便于后面读取该变量的线程获取到的是最新的值。这里volatile的特性可能一眼就能够看清...原创 2019-12-31 15:52:56 · 2184 阅读 · 0 评论 -
Hashmap底层实现 JDK8
hashmap的底层实现(jdk1.8)数据结构底层真正存储数据的是一个table数组,实际的数据结构是一个散列表,用链表来处理冲突,散列表相关知识可查阅数据结构教材(盗个图)。Node<K,V>结构如下:Put(K,V)方法分析 public V put(K key, V value) { return putVal(has...原创 2019-03-31 10:12:47 · 273 阅读 · 0 评论 -
jdk 1.7 ConcurrentHashmap的底层原理
ConcurrentMashmap与HashTable的区别ConcurrentMashmap和HashTable都是线程安全的。HashTable内部通过一个table[ ] 来存储数据,然后通过给put,get等方法加上synchronized方法来实现同步,虽然实现同步了,但是导致一个线程获得了锁,其它线程就不能执行put和get操作,这在高并发情况下效率非常低。当然这里的前提是这个Ha...原创 2019-04-01 21:05:36 · 629 阅读 · 2 评论