Java并发编程
terrybg
分享Java、微服务、架构、前端、项目管理技术,欢迎一起交流。
展开
-
【Java并发编程 工作窃取】29.ForkJoin分支合并框架和Java8 Stream并行
如果计算大单位的数值,可以使用ForkJoinPool来实现,它的原理是将一个大任务,通过递归拆分成很多小任务,每一个小任务就是一个线程来执行。实现步骤:通过ForkJoin计算0~1亿的总合:打印结果:ForkJoin框架计算 得出结果:5000000050000000ForkJoin 对比普通单线程 和java8 运算时间。打印结果(计算结果不是绝对的,会随着机器不同而影响,java8性能最差?):为了更细致的看结果:我们对这3种方式 通过如下比较:分别拆成3个方法,数据大小比较,cpu占用率比原创 2022-06-05 08:15:00 · 10285 阅读 · 0 评论 -
【Java并发编程 线程池】28.ThreadPoolExcutor和自定线程池
线程池底层使用**堵塞式队列 **。队列遵从:先进先出,后进后出原则。阻塞队列(BlockingQueue)和非阻塞队列(ConcurrentLinkedQueue )区别:无界和有界队列:ConcurrentLinkedQueue 是无界队列,不用设置长度,可以随便存放值(其实是jdk伪造的,最大长度是Integer的最大值)BlockingQueue 是有界队列,需要设置长度。注意:如果BlockingQueue 不设置等待时间就是非阻塞队列存入:非阻塞队列:如果存放超出了队列总数,添加不进原创 2022-06-05 07:45:00 · 10267 阅读 · 0 评论 -
【Java并发编程 线程池】27.线程池概念和Executor封装的四种线程池
创建若干个线程,放入池中,有任务需要处理了就提交到任务队列中,处理完不会销毁线程,而是仍然在任务队列中等待下个任务。重复利用提高响应速度(没有cpu时间调度)管理线程Executor封装好了四种连接池类型newCachedThreadPool:缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。(工作中用的比较多)newScheduledThreadPool:创建固定大小的线程,可以延原创 2022-06-05 07:30:00 · 10444 阅读 · 0 评论 -
【Java并发编程 队列】26.BlockingQueue 阻塞队列
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。 阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容 器,而消费者也只从容器里拿元素。BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:ArrayBlockingQue原创 2022-06-05 07:15:00 · 10179 阅读 · 0 评论 -
【Java并发编程 队列】25.ConcurrentLinkedQueue 高性能无锁队列
是一个适用于高并发场景下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue.它是一个基于链接节点的无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先加入的,尾是最近加入的,该队列不允许null元素。...原创 2022-06-04 09:43:23 · 10655 阅读 · 1 评论 -
【Java并发编程 AQS】24.Semaphore信号量
Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:availablePermits函数用来获取当前可用的资源数量wc.acquire(); //申请资源wc.release();// 释放资源semph原创 2022-06-04 09:42:13 · 10108 阅读 · 0 评论 -
【Java并发编程 AQS】23.CyclicBarrier同步屏障
当线程达到一定的次数,并行执行。代码如下:打印结果:原创 2022-06-04 09:41:14 · 10121 阅读 · 0 评论 -
【Java并发编程 AQS】22.CountDownLatch计数器
当线程执行数量达到你规定的数量时,被阻塞的线程才会继续运行。现在有一个需求,要计算在多线程环境下耗时如下代码:上述代码会出现这种情况:主线程已经跑完了,但是子线程还在执行。就是说主线程是计算时间,但是还有子线程执行,如何让主线程计算时间的代码最后执行呢?使用CountDownLatch:如果不用CountDownLatch也可以实现,在countDownLatch.await()处改成while(true)的判断线程是否执行完毕,执行完毕break掉,因为CountDownLatch底层是AQS(原创 2022-06-04 09:39:53 · 10157 阅读 · 0 评论 -
【Java并发编程 线程安全】21.线程安全集合
1.Vector(已过时)在Java早期使用Vector,在remove、get、set、add、size都是通过synchronized修饰,但是Vector已经过时了,效率比较慢。2.Synchronized或者ReentrantLock修饰3.Collections.synchronizedListCollections.synchronizedList底层返回的是SynchronizedList,关键代码是同步代码块如下:4.CopyOnWriteArrayList(写数组的拷贝)多线程环境使原创 2022-06-04 09:37:07 · 10450 阅读 · 0 评论 -
【Java并发编程 线程安全】20.读写锁ReentrantReadWriteLock
读写锁又称互斥锁:相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(也就是说:读-读能共存,读-写不能共存)。下面看一下模拟缓存的例子,一个线程写,一个线程读:这就出现问题了,当一个线程还没有写人完毕,另外一个线程进行了读操作原创 2022-06-04 20:15:23 · 10398 阅读 · 0 评论 -
【Java并发编程 线程安全】19.重入锁
重入锁:在java中有synchronized,和 lock接口下的ReentrantLock都属于重入锁重入锁特点:锁传递,当线程中使用多个同样的锁,会传递下去。也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。非重入锁会造成死锁现象我们看一下线程调用例子:方法调用没规律,get和set连续调用两次get,set交替执行。使用ReentrantLock(和synchronized效果一样):...原创 2022-06-04 07:30:00 · 10315 阅读 · 0 评论 -
【Java并发编程 线程安全】18.Java20种锁整理
概念:假设最坏的情况,任何线程操作资源都要加锁。Java中的应用:Java中的synchronized、ReentrantLock等,数据库中的行锁、表锁,读锁,写锁都是这种机制,操作之前先上锁。应用场景:悲观锁适合写多操作。概念:假设最好的情况,每次拿数据都不会认为会更改,而是在这期间去判断有没有更新数据。Java中的应用:Java中的CAS算法Atomic原子类就是乐观锁。缺点:ABA问题、循环时间长开销大、只能保证一个共享变量的原子操作应用场景:乐观锁适合读多操作。概念:让线程一直处于等待状态,做我旋原创 2022-06-03 17:58:55 · 10868 阅读 · 0 评论 -
【Java并发编程 线程安全】17.线程通讯lock、condition
使用Lock锁可以代替synchronized,那么它的线程通讯该怎么用呢?使用Condition搭配Lock锁实现线程通讯,在Condition对象中,与wait、notify、notifyAll对应的方法是await、signal、signalAll。先看一下之前生产者与消费者的例子:使用lock锁与Condition搭配:...原创 2022-06-03 17:58:16 · 10371 阅读 · 0 评论 -
【Java并发编程 线程安全】16.线程通讯wait、notify
当一个线程完成了一个任务的时候,通知给另外一个线程去处理其它事情。常见例子是生产者与消费者,弄明白这个对学习mq(消息中间件)很有帮助打印如下:可以看到是交替执行的原创 2022-06-03 17:57:15 · 10340 阅读 · 0 评论 -
【Java并发编程 线程安全】15.Atomic原子类和CAS算法
在使用volatile关键字后,并不会完全解决线程安全问题,它只是解决线程可见性问题。jdk1.5后推出了并发包:java.util.concurrent.atomic可以解决线程原子性的问题。常用方法依然存在数据问题打印如下:i++的原子性问题:i++ 的操作实际分了三个步骤“读-改-写”atomic特性在java.util.concurrent.atomic可以解决线程原子性的问题 , 类如下:使用AtomicInteger打印如下:...原创 2022-06-03 17:56:21 · 10467 阅读 · 0 评论 -
【Java并发编程 线程安全】14.线程可见性volatile关键字
问题分析虽然修改了flag ,但是仍会出现死循环。原因:值是不可见,线程读取到的值都是副本。解决办法使用Volatile关键字将解决线程之间可见性, 强制线程每次读取该值的时候都去“主内存”中取值。volatile能解决原子性问题?volatile能解决线程可见性问题,但是原子性却无法解决,如i++操作;...原创 2022-06-03 17:55:27 · 10384 阅读 · 0 评论 -
【Java并发编程 线程安全】13.Java内存模型和线程安全三大特性
Java内存模型即Java Memory Model,简称JMM。注意:Java内存模型不是像堆内存,方法区,栈内存类似的东西,这个叫Java内存结构。Java内存模型跟多线程有关。java内存模型,决定一个线程是否与另外一个线程可见性,在java内存模型中分为主内存(共享的变量)和私有本地内存(也可以叫工作内存,本地线程私有的变量)主内存与工作内存:Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有原创 2022-06-03 17:54:39 · 10486 阅读 · 0 评论 -
【Java并发编程 线程安全】12.死锁现象和如何排查死锁问题
多线程死锁现象,同步中嵌套同步,无法释放锁,一直等待,变成死锁最后谁都没有吹上空调,两条线程依旧停第二把锁那里,打印如下:产生原因:java同步机制解决了线程安全问题,但是同时也引发了死锁现象。死锁现象如何解决:没法解决,只能尽量避免死锁现象。死锁出现的根本原因:1.互斥资源必须处于非共享模式,即一次只有一个进程可以使用。如果另一进程申请该资源,那么必须等待直到该资源被释放为止。2.占有并等待一个进程至少应该占有一个资源,并等待另一资源,而该资源被其他进程所占有。3.非抢占资源不能被抢占。只能在持原创 2022-06-03 17:53:39 · 10567 阅读 · 0 评论 -
【Java并发编程 线程安全】11.Lock锁解决线程安全问题
从JDK5之后,Java提供了另外一种线程同步机制:它通过显示定义同步锁对象来实现同步,在这种机制下,同步锁应该使用Lock对象充当。通常认为:Lock提供了比synchronized方法和synchronized代码块更广泛的锁定操作,Lock实现允许更灵活的结构,可以具有差别很大的属性,并且可以支持多个相关的Condition对象。Lock是控制多个线程对共享资源进行访问的工具。通常,所提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。不过原创 2022-06-03 17:53:05 · 10523 阅读 · 0 评论 -
【Java并发编程 安全】10.线程安全概念和synchronized用法
当多个线程同时对同一资源访问,并且写的时候,可能会受到其它线程干扰,导致数据问题,这种现象被称之为线程安全问题。(多线程读的时候不会产生线程安全问题)可以看到下面多处数据问题,概率还是很大的线程如何同步,保证数据的原子性。解决方案:synchronized 特点:自动挡lock jdk1.5(并发包中) 特点:手动锁(需要手动开启和关闭)同步代码块执行结果:改成调用同步函数:可以看到出现线程问题了,注意:同步函数的锁对象是this,每次线程进行判断的时候拿的不是同一把锁。解决方法:方案二:原创 2022-06-03 17:52:00 · 10347 阅读 · 0 评论 -
【Java并发编程 基础】9.线程异常处理
JDK自带的stop不推荐使用,主要是线程不安全,可能会出现数据不同步,推荐使用自定义标识停止线程打印输出:原创 2022-06-03 08:30:00 · 10413 阅读 · 0 评论 -
【Java并发编程 基础】8.自定义线程停止
JDK自带的stop不推荐使用,主要是线程不安全,可能会出现数据不同步,推荐使用自定义标识停止线程打印输出:原创 2022-06-02 22:57:35 · 10335 阅读 · 0 评论 -
【Java并发编程 基础】7.线程谦让yield
Thread.yield()方法的作用:暂停当前正在执行的线程,并执行其他线程。(可能没有效果)yield()让当前正在运行的线程回到可运行状态,以允许具有相同优先级的其他线程获得运行的机会。因此,使用yield()的目的是让具有相同优先级的线程之间能够适当的轮换执行。但是,实际中无法保证yield()达到让步的目的,因为,让步的线程可能被线程调度程序再次选中。结论:大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。用户线程和主线程例子:打印输出,可以看到不一定起到效果:.原创 2022-06-03 08:15:00 · 10262 阅读 · 0 评论 -
【Java并发编程 基础】6.线程让步join
join作用是让其他线程变为等待,t1.join();//让其他线程变为等待,直到当前t1线程执行完毕,才释放。thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。public final void join() throws InterruptedException;public final synchronized void join(long millis) throw原创 2022-06-03 08:00:00 · 10333 阅读 · 0 评论 -
【Java并发编程 基础】5.守护线程
在java中有两种线程:用户线程,守护线程。用户线程 指用户创建的线程,主线程停止用户线程不会停止守护线程 当进程结束或主线程停止,守护线程也会停止守护线程和main相关(主线程),gc线程(垃圾回收器)也是守护线程,当主线程死掉后,gc线程也会死。用户线程和主线程例子:当主线程执行完毕后,用户线程依然在执行主线程和守护线程例子:可以看到主线程执行完后,守护线程就不会执行完了,虽然执行到了16原创 2022-06-03 07:45:00 · 10788 阅读 · 0 评论 -
【Java并发编程 基础】4.线程状态
线程分为了六种状态,如下:初始状态(NEW):线程被构建,但是还没有调用start状态运行状态(RUNNABLE):就绪和运行笼统称为运行中等待状态分三种阻塞状态(BLOCKED):等待调用synchronized等待状态(WAITING):调用了wait方法超时等待(TIME_WAITING):不同于等待,是到达一定的时间自动进入运行状态(Thread.sleep)终止状态(TERMINATED): 表示当前线程执行完毕1.1、join(合并线程,等待该线程终止)在没调用join之前,线程跑的是不规原创 2022-06-02 18:39:13 · 10413 阅读 · 0 评论 -
【Java并发编程 基础】3.Thread常用方法
Thread类中常用线程属性、设置优先级、设置线程状态、常用Thread构造函数总结原创 2022-06-02 18:28:40 · 10436 阅读 · 0 评论 -
【Java并发编程 基础】2.线程常见8种创建方式
上篇文章主要介绍了多线程的概念,本篇文章主要描述Java中8种常见创建线程方式:该种方式是java最原始的方式使用方式:2.通过实现Runable创建实现Runable接口在继承Thread基础上解决了Java单继承的问题。使用方式:3.Callable和Future的方式Java提供了Callable接口,是对Runnable接口的增强版,Callable接口也提供了一个call方法可以作为线程执行体,但call方法比run方法功能更强大:call()方法有返回值call()方法可以声明抛原创 2022-06-02 17:58:32 · 10164 阅读 · 0 评论 -
【Java并发编程 基础】1.多线程的概念
是操作系统中可调度任务最小单位,在JVM中可以一个进程能够运行多个线程分别执行不同的任务进程是资源分配最小单位线程是程序执行的最小单位对于如果使用单核cpu服务器,开启多线程的情况下,并不是真正意义上的多线程,因为单核cpu服务器在同一个时刻最多只能运行一个线程,当正在运行的线程快速切换到另外一个线程执行,这个过程我们可以称之为Cpu切换。同步:指必须等待全部执行完才能执行后续的行为。异步:方法调用会理解返回,调用者可以继续后续的操作并发是指一个处理器同时处理多个任务。并行是指多个处理器或者是多核的处原创 2022-06-02 17:54:58 · 10355 阅读 · 0 评论