
多线程
文章平均质量分 82
多线程
爱上口袋的天空
一步一流年,止不住的脚步,挽不回的青春!
展开
-
LinkedBlockingQueue 的使用
1、add 方法:如果队列已满,报java.lang.IllegalStateException: Queue full 错误。2、peek 方法:返回队列顶元素,但顶元素不弹出,队列为空时返回null。2、offer 方法:如果队列已满,程序正常运行,只是不再新增元素。1、poll 方法:弹出队顶元素,队列为空时返回null。3、put 方法:如果队列已满,阻塞。3、take 方法:当队列为空,阻塞。原创 2023-08-25 18:55:27 · 938 阅读 · 0 评论 -
Java8 CompletableFuture 用法全解
一、简介 CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调、流式处理、多个Future组合处理的能力,使Java在处理多任务的协同工作时更加顺畅便利。二、创建异步任务1、Future.submit 通常的线程池接口类ExecutorService,其中execute方法的返回值是void,即无法获取异步任务的执行状态,3个重载的submit方法的返回值是Future,可以据...转载 2021-09-05 16:58:29 · 983 阅读 · 0 评论 -
Future和FutureTask的区别
直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Callable接口配合起来使用。总的来说Future模式的思想就是在子线程进行执行的时候,主线程不阻塞继续执行。等到主线程需要子线程的结果的时候再去获取子线程的结果(此时子线程没有执行完成的话就会阻塞直至执行完成)。转载 2021-09-05 12:28:02 · 150 阅读 · 0 评论 -
FutureTask是什么?
这个其实前面有提到过,FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。原创 2021-09-05 11:22:22 · 2561 阅读 · 0 评论 -
ReadWriteLock是什么?
首先明确一下,不是说ReentrantLock不好,只是ReentrantLock某些时候有局限。如果使用ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。因为这个,才诞生了读写锁ReadWriteLock。转载 2021-09-05 09:59:55 · 159 阅读 · 0 评论 -
什么是AQS?
AQS,是AbstractQueuedSynchronizer简称,直翻过来叫抽象的队列式同步器, 也可以称作队列同步器,它是java.util.concurrent.lock包下的一个工具类。直观来讲,AQS是Java提供的一个类,这个类是被Abstract修饰的,需要被子类继承。也就是说AQS是Java并发中用以解决多线程访问共享资源问题的同步机制的基本的框架(或者说是一种规范),为Java并发同步组件提供统一的底层支持。即,AQS是个为各个同步组件提供基本框架的一个抽象类。转载 2021-09-04 22:51:37 · 94 阅读 · 0 评论 -
什么是Future?
在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。...转载 2021-09-04 22:13:15 · 78 阅读 · 0 评论 -
初识CAS锁(概述、底层原理、原子引用、自旋锁、缺点)
CAS的全称为Compare-And-Swap,直译就是对比交换。是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值。经过调查发现,其实现方式是基于硬件平台的汇编指令,就是说CAS是靠硬件实现的,JVM只是封装了汇编调用,那些AtomicInteger类便是使用了这些封装后的接口。CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下在旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。转载 2021-09-04 22:11:40 · 1793 阅读 · 0 评论 -
什么是CAS?
CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通转载 2021-09-04 22:09:21 · 5027 阅读 · 0 评论 -
CyclicBarrier和CountDownLatch的区别
CountDownLatch和CyclicBarrier都有让多个线程等待同步然后再开始下一步动作的意思,但是CountDownLatch的下一步的动作实施者是主线程,具有不可重复性;而CyclicBarrier的下一步动作实施者还是“其他线程”本身,具有往复多次实施动作的特点。原创 2021-09-04 22:02:22 · 47 阅读 · 0 评论 -
Java四种线程池创建方式
。转载 2021-09-04 21:33:45 · 813 阅读 · 0 评论 -
Java如何正确停止线程
俗话说:上山容易下山难。知道如何启动线程,那么到底如何停止线程呢?本文将讲解Java中三种场景下如何正确的停止线程,分别是普通情况、堵塞状态、循环中堵塞状态,三种情况下如何正确的停止线程。转载 2021-09-04 20:36:54 · 621 阅读 · 0 评论 -
线程池的线程复用原理
在线程池中,通过同一个线程去执行不同的任务,这就是线程复用。假设现在有 100 个任务,我们创建一个固定线程的线程池(FixedThreadPool),核心线程数和最大线程数都是 3,那么当这个 100 个任务执行完,都只会使用三个线程。转载 2021-09-04 17:27:30 · 479 阅读 · 0 评论 -
Java:强引用,软引用,弱引用和虚引用
在实际程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生利用软引用和弱引用解决OOM问题:假如有一个应用需要读取大量的本地图片,如果每次读取图片都从硬盘读取,则会严重影响性能,但是如果全部加载到内存当中,又有可能造成内存溢出,此时使用软引用可以解决这个问题。转载 2021-09-04 11:51:27 · 60 阅读 · 0 评论 -
ThreadLocal作用、场景、原理
ThreadLoal 变量,,也有些地方叫做,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。转载 2021-09-04 11:25:04 · 92 阅读 · 0 评论 -
对守护线程的理解
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。原创 2021-08-30 22:09:13 · 93 阅读 · 0 评论 -
sleep()、wait()、join()、yield()的区别
wait: Object的方法,常和notify(notifyAll)+synchronized一起使用,调用wait后,线程会释放自己持有的锁及cpu资源,进入线程等待池中,等待其他线程唤醒它。sleep: Thread的方法,可以设置休眠时间,让线程进入就绪状态。在这期间,线程只会释放CPU资源,如果此时持有的锁资源,则不会释放,时间到了之后继续运行。yield: Thread的方法,有点类似于sleep,只是不能设置时间。转载 2021-08-29 23:21:47 · 474 阅读 · 0 评论 -
多线程并发拓展
一、死锁1、死锁的定义所谓的死锁是指两个或两个以上的线程在等待执行的过程中,因为竞争资源而造成的一种互相等待的现象。若不受外力作用,他们都将无法推进下去。此时,处于系统中所处的状态就是死锁。2、发生死锁所必须具备的条件:互斥条件:它是指进程对所分配的资源进行排他性的使用,在一定时间内,某资源只由一个进程在用,如果此时还有其他进程请求资源,请求者只能等待。直到占有资源的进程用完或释放之后才可以继续使用。请求和保持条件:它是指进程已经保持了至少一个资源,又提出了新的资源请求,该资源已被其它转载 2021-08-22 14:29:32 · 157 阅读 · 0 评论 -
自定义线程池工具类
import java.util.concurrent.*; /** * 线程池工具类: * 处理项目中需要异步处理的任务,例如日志服务,监控服务等 * @author zsc * @datetime 2017年11月22日 上午11:04:09 */public class ThreadPoolUtil { /** 工具类,构造方法私有化 */ private ThreadPoolUtil() {super();}; // 线程池核心线程数 private final.转载 2021-08-08 18:57:29 · 260 阅读 · 0 评论 -
Java中的线程池(Thread Pools)配置详解
线程池的优点Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中,合理地使用线程池能够带来3个好处。 降低资源消耗。 通过重复利用已创建的线程来降低线程创建和销毁的造成的消耗 提高响应速度 当任务到达时,任务可不用等待线程创建就能立即执行 提高线程的可管理性 线程是稀缺资源,不能无限制的创建,使用线程池可以进行统一分配、调优和监控,增强稳定性。 线程池的实现原理当向线程池提交一个任务之后,线程池是如何处理这转载 2021-08-08 18:25:21 · 519 阅读 · 0 评论 -
Java-多线程框架Executor(下)
概述在Java中,使用线程来异步执行任务。Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源。同时,为每一个任务创建一个新线程来执行,这种策略可能会使处于高负荷状态的应用最终崩溃。Java线程既是工作单元,也是执行单元。从JDK1.5开始,把工作单元与执行机制分离开来。工作单元包括Runnable 和 Callable,而执行机制由Executor框架提供。Java从1.5版本开始,为简化多线程并发编程,引入全新的并发编程包转载 2021-08-08 17:43:58 · 504 阅读 · 0 评论 -
Java多线程之线程池 Executor(上)
new Thread的弊端每次new Thread 新建对象,性能差。 线程缺乏统一管理,可能无限制的新建线程,相互竞争,可能占用过多的系统资源导致死机或者OOM(out of memory 内存溢出),这种问题的原因不是因为单纯的new一个Thread,而是可能因为程序的bug或者设计上的缺陷导致不断new Thread造成的。 缺少更多功能,如更多执行、定期执行、线程中断线程池的好处重用存在的线程,减少对象创建、消亡的开销,性能好。 可有效控制最大并发线程数,提高系统资源利用率,同时转载 2021-08-08 16:50:44 · 384 阅读 · 0 评论 -
并发编程-J.U.C组件拓展之阻塞队列BlockingQueue
概述阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法. 支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满 支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空 阻塞队列的常用场景阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。阻塞队列的4种处理方式.转载 2021-08-07 11:47:09 · 248 阅读 · 0 评论 -
并发编程-J.U.C组件拓展之Fork/Join框架
Fork/Join框架概述Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。工作窃取算法工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行.假如我们需要做一个比较大的任务,可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,把这.翻译 2021-08-07 11:22:21 · 262 阅读 · 0 评论 -
并发编程-J.U.C组件拓展之Future和FutureTask
1、概述Future接口和实现Future接口的FutureTask类,代表异步计算的结果。FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用线程直接执行(FutureTask.run())。2、FutureTask的三种运行状态根据FutureTask.run()方法被执行的时机,FutureTask可以处于下面3种状态未启动。FutureTask.run()方法还没有被执行之前,转载 2021-08-07 11:10:38 · 284 阅读 · 0 评论 -
并发编程-AQS同步组件之重入锁ReentrantLock、 读写锁ReentrantReadWriteLock、Condition
ReentrantLock概述重入锁ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,而不会造成自己阻塞自己。重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞ReentrantLock虽然没能像synchronized关键字一样支持隐式的重进入,但是在调用lock()方法时,已经获取到锁的线程,能够再次调用lock()方法获取锁而不被阻塞。除此之外,该锁的还支持获取锁时的公平和非公平性选择。实际上,公平的锁机制往往没有非转载 2021-08-01 17:52:42 · 310 阅读 · 1 评论 -
并发编程-AQS同步组件之 CyclicBarrier 同步屏障
CyclicBarrierCyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。当某个线程调用了await方法之后,就会进入等待状态,并将计数器-1,直到所有线程调用await方法使计数器为0,才可以继续执行,由于计数器可以重复使用,所以我们又叫它循环屏障。CyclicBarrier默认的构造方法是CyclicBar转载 2021-08-01 17:28:20 · 276 阅读 · 0 评论 -
并发编程-AQS同步组件之 Semaphore 控制并发线程数的信号量
Semaphore 概述Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。举个例子:高速要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须 在路口等待,所以前一百辆车会看到绿灯,可以开进这条高速,后面的车会看到红灯,不能驶入高速,但是如果前一百辆中有5辆车已经离开了高速,那么后面就允许有5辆车驶入高速,这个例子里说的车就是线程,驶入高速就表示线程在执行,离开高速就表示线程执行完成,看见红灯就表示线程被阻塞,不能执行。.转载 2021-08-01 17:10:51 · 250 阅读 · 0 评论 -
并发编程-AQS同步组件之CountDownLatch 闭锁
CountDownLatch闭锁 Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能。 CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待 ,即CountDownLatch允许一个或多个线程等待其他线程完成操作。 闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行: 确保某个计算在其需要的所有资源都被初始化之转载 2021-08-01 16:37:46 · 425 阅读 · 0 评论 -
并发编程-并发容器(J.U.C)核心 AbstractQueuedSynchronizer 抽象队列同步器AQS介绍
J.U.C脑图了体现出AQS和线程池的重要性,上图单独将AQS和线程池拿出来了。J.U.C的构成如下:J.U.C核心AQS简介AQS(AbstractQueuedSynchronizer)是并发容器中的同步器,AQS是J.U.C的核心,它是抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,我们常用的ReentrantLock、Semaphore、CyclicBarrier、ReentrantLock、Condition、FutureTask都依赖于...转载 2021-08-01 13:08:19 · 252 阅读 · 0 评论 -
并发编程-线程安全策略之并发容器(J.U.C)中的集合类
JUC 是 Java 5.0 之后新增的一个包,该包提供了一套并发编程的工具类,包括原子操作、线程池、Lock、Condition 等类,方便进行多线程编程的操作。JUC 的出现是为了解决多线程共享资源,协作完成任务时常见的问题,如同时访问共享资源、线程死锁、饥饿、并行性不足等问题。使用 JUC 提供的工具类可以简化并发程序的编写,提高程序的效率和稳定性同步容器是通过synchronized来实现同步的,所以性能较差。而且同步容器也并不是绝对线程安全的,在一些特殊情况下也会出现线程不安全的行为。转载 2021-07-31 19:14:18 · 308 阅读 · 0 评论 -
并发编程-线程安全策略之两种类型的同步容器
脑图概述之前讲了一些常用的线程不安全的集合容器(ArrayList、HashMap、HashSet),如果有多个线程并发访问这些集合时就会出现线程不安全的问题。 当我们在使用这些容器时,需要我们自己来处理线程安全的问题。 使用起来相对会有些不便,而Java在这方面提供了相应的同步容器,我们可以在多线程情况下可以结合实际场景考虑使用这些同步容器。同步容器集合接口下的同步容器实现类Vector的方法都是由synchronized关键字保护ctrl + o,方法左侧 带有,.转载 2021-07-31 18:42:25 · 266 阅读 · 0 评论 -
并发编程-线程安全策略之常见的线程不安全类
脑图概述前两篇博客,我们说了 通过不可变变量和线程封闭这两种方式来实现线程安全。这里我们来介绍下很常见的线程不安全的类所谓线程不安全的类,是指一个类的实例对象可以同时被多个线程访问,如果不做同步或线程安全的处理,就会表现出线程不安全的行为,比如逻辑处理错误、抛出异常等。字符串拼接之StringBuilder、StringBufferStringBuilder一个可变的字符序列。它继承于AbstractStringBuilder,实现了CharSequence接口。 ...转载 2021-07-31 17:24:22 · 960 阅读 · 0 评论 -
并发编程-线程安全策略之线程封闭
脑图概述我们通过介绍使用线程安全的不可变对象可以保证线程安全。除了上述方法,还有一种办法就是:线程封闭。线程封闭的三种方式Ad-hoc 线程封闭,完全由程序控制实现,不可控,不要使用 堆栈封闭方法中定义局部变量。不存在并发问题堆栈封闭其实就是方法中定义局部变量。不存在并发问题。多个线程访问一个方法的时候,方法中的局部变量都会被拷贝一份到线程的栈中(Java内存模型),所以局部变量是不会被多个线程所共享的。局部变量的固有属性之一就是封闭在线程中。它们位于...转载 2021-07-31 16:37:21 · 266 阅读 · 0 评论 -
并发编程-线程安全策略之不可变对象
脑图四个线程安全策略线程限制一个被线程限制的对象,由线程独占,并且只能被占有它的线程修改共享只读一个共享只读的对象,在没有额外同步的情况下,可以被多个线程并发访问,但是任何线程都不能修改它线程安全对象一个线程安全的对象或者容器,在内部通过同步机制来保证线程安全,所以其他线程无需额外的同步就可以通过公共接口随意访问它被守护对象被守护对象只能通过获取特定的锁来访问不可变对象定义在Java中,有一种对象发布了就是安全的,被称之为不可变对象。..转载 2021-07-31 12:05:26 · 512 阅读 · 0 评论 -
Java并发编程与高并发解决方案--安全发布对象
发布对象使一个对象能够被当前范围之外的代码所使用private String [] states = {"a", "b", "c"};......public static void main(String[] args) { a = new UnsafePushlish(); log.info("输出修改前信息"); //结果为a , b , c a.getSates()[0] = "d"; log.info("输出修改后信息");转载 2021-07-31 11:34:55 · 193 阅读 · 0 评论 -
Java多线程安全可见性和有序性之Volatile
可见性什么是可见性一个线程对主内存的修改可以及时的被其他线程观察到。导致共享变量在线程间不可见的原因线程交叉执行 重排序结合线程交叉执行 共享变量更新后的值没有在工作内存与主存间及时更新 JVM处理可见性 JVM对于可见性,提供了synchronized和volatileJMM关于synchronized的两条规定线程解锁前,必须把共享变量的最新值刷新到主内存。 线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意:加锁与解锁是同一转载 2021-07-25 15:37:18 · 235 阅读 · 0 评论 -
Java多线程安全原子性之Atomic、CAS、Synchronized和Lock
一、线程安全线程安全概述当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。线程安全性概述线程安全性主要体现在三个方面:原子性、可见性、有序性。原子性: 提供了互斥访问,同一时刻只能有一个线程来对它进行操作。 可见性: 一个线程对主内存的修改可以及时的被其他线程观察到。 有序性: 一个线程观察其他线程中的指令执行顺序,由于指令重排序的存在,该观转载 2021-07-25 13:21:09 · 858 阅读 · 0 评论 -
Java内存模型
1、简介 Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的。Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型。 如果你想设计表现良好的并发程序,理解Java内存模型是非常重要的。Java内存模型规定了如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。 原始的Java内存模型存在一些不足,因此Java内存模型在Java1.5时被重新修订。这个版本的J...转载 2021-07-24 15:30:22 · 150 阅读 · 0 评论 -
CountDownLatch的简单理解
CountDownLatch的概念CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成了任务,然后在CountDownLatch上等待的线程就可以恢复执行任务。CountDownLatch的概念翻译 2021-03-02 10:18:45 · 168 阅读 · 0 评论