Semaphore 与ThreadPoolExecutor 的使用】的更多相关文章

1. Semaphore 信号量  (阻塞) 优点:可以控制线程的数量,不会超出线程范围 缺点:当线程死锁时,永远没法释放,导致一直阻塞 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或逻辑的)线程数目. 一个信号量有且仅有3种操作,且它们全部是原子的:初始化.增加和减少 增加可以为一个进程解除阻塞: 减少可以让一个进程进入阻塞. 如何获得Semaphore对象?     public Se…
官方解释: 一个计数信号量.在概念上,信号量维持一组许可证.如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它.每个release()添加许可证,潜在地释放阻塞获取方.但是,没有使用实际的许可证对象; Semaphore只保留可用数量的计数,并相应地执行.信号量通常用于限制线程数,而不是访问某些(物理或逻辑)资源 我记得考科目一的时候有一个大教室,这个教室只能同时允许两百人考试,当有一个考完之后,下一个才能进去进行考试.门口会有安检人员进行安检,这个Semaphore就相…
ReentrantLock/CountDownLatch/Semaphore/FutureTask/ThreadPoolExecutor的源码中都会包含一个静态的内部类Sync,它继承了AbstractQueuedSynchronizer这个抽象类. AbstractQueuedSynchronizer是java.util.concurrent包中的核心组件之一,为并发包中的其他synchronizers提供了一组公共的基础设施. AQS会对进行acquire而被阻塞的线程进行管理,其管理方式是…
申明:此篇文章转载自:https://juejin.im/post/5c11d6376fb9a049e82b6253写的真的很棒,感谢老钱的分享. 打通 Java 任督二脉 —— 并发数据结构的基石 每一个 Java 的高级程序员在体验过多线程程序开发之后,都需要问自己一个问题,Java 内置的锁是如何实现的?最常用的最简单的锁要数 ReentrantLock,使用它加锁时如果没有立即加成功,就会阻塞当前的线程等待其它线程释放锁之后再重新尝试加锁,那线程是如何实现阻塞自己的?其它线程释放锁之后又…
一.引言在JDK1.5之前,一般是靠synchronized关键字来实现线程对共享变量的互斥访问.synchronized是在字节码上加指令,依赖于底层操作系统的Mutex Lock实现.而从JDK1.5以后java界的一位大神—— Doug Lea 开发了AbstractQueuedSynchronizer(AQS)组件,使用原生java代码实现了synchronized语义.换句话说,Doug Lea没有使用更“高级”的机器指令,也不依靠JDK编译时的特殊处理,仅用一个普普通通的类就完成了代…
CAS 对应cpu的硬件指令, 是最原始的原子操作 cas主要是在AtomicInteger AtomicXXX类中使用, 用于实现线程安全的自增操作 ++. 对应一个unsafe对象, 根据os平台的不同,操作cpu指令c++代码有少许不同 compareAndSetState(int expect, int update) 在当前值==expect时,变更为update值 AQS 全称是AbstractQueuedSynchronizer, 它是基于cas的锁同步框架,这个类是抽象的,其中有…
Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线程池的创建类 ThreadPoolExecutor.Executors 等: 提供了各种锁,如 Lock.ReentrantLock 等: 提供了各种线程安全的数据结构,如 ConcurrentHashMap.LinkedBlockingQueue.DelayQueue 等: 提供了更加高级的线程同…
我们知道,在java中提供了两类锁的实现,一种是在jvm层级上实现的synchrinized隐式锁,另一类是jdk在代码层级实现的,juc包下的Lock显示锁,而提到Lock就不得不提一下它的核心队列同步器(AQS)了,它的全称是AbstractQueuedSynchronizer,是用来构建锁或者其他一些同步组件的基础,除了ReentrantLock.ReentrantReadWriteLock外,它还在CountDownLatch.Semaphore以及ThreadPoolExecutor中…
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭锁CountDownLatch 与 栅栏CyclicBarrier 并发编程 05—— Callable和Future 并发编程 06—— CompletionService : Executor 和 BlockingQueue 并发编程 07—— 任务取消 并发编程 08—— 任务取消 之 中断…
前言 线程池可以提高程序的并发性能(当然是合适的情况下),因为对于没有线程的情况下,我们每一次提交任务都新建一个线程,这种方法存在不少缺陷: 1.  线程的创建和销毁的开销非常高,线程的创建需要时间,会延迟任务的执行,会消耗大量的系统资源. 2.  活跃的线程会消耗系统资源,而大量的空闲线程会占用许多内存,给垃圾回收器带来很大的压力,而大量线程在竞争CPU资源的时间还会产生气体的性能开销. 3.  系统在可创建的线程上存在一个限制,如果超过了这个限制,很可能抛出OOM. 我们不难发现,在一定范围…
我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结下Java并发编程中的4个类CountDownLatch.CyclicBarrier.Semaphore.Phaser. 1.CountDownLatch CountDownLatch可以理解为一个计数器在初始化时设置初始值,当一个线程需要等待某些操作先完成时,需要调用await()方法.这个方法让线程进入休…
上次简单了解了多线程中锁的类型,今天要简单了解下多线程并发控制的一些工具类了. 1. 概念说明: CountDownLatch:相当于一个待执行线程计数器,当计数减为零时表示所有待执行线程都已执行完毕,等待被计数线程结果的(即使用await()的)线程可以继续执行(await()后面的代码)了. CyclicBarrier:可循环屏障,相当于一个准备执行线程计数器,当计数减为零时表示所有待执行线程(这些线程需要同时开始工作)都已做好准备工作,可以开始工作了. Semaphore:允许并发线程数,…
方法我们通过继承Thread类和实现runnable接口或者callable接口三种方式实现. 继承Thread类实际上也是实现了runnable接口,被继承的类主要是实现run()方法,通过start()方法调用. 而callable接口是属于Executor 对比与Runnable接口功能的区别是: (1).Callable可以在任务结束后提供一个返回值,Runnable没有这个功能 (2).Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常 (…
Semaphore用于管理信号量,在并发编程中,可以控制返访问同步代码的线程数量.Semaphore在实例化时传入一个int值,也就是指明信号数量.主要方法有两个:acquire()和release().acquire()用于请求信号,每调用一次,信号量便少一个.release()用于释放信号,调用一次信号量加一个.信号量用完以后,后续使用acquire()方法请求信号的线程便会加入阻塞队列挂起.本篇简单分析Semaphore的源码,说明其实现原理. Semaphore对于信号量的控制是基于AQ…
一.CountDownLatch用法 CountDownLatch类位于java.util.concurrent中包下,利用它可以实现类似计数器的功能.比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了. CountDownLatch类只提供了一个构造器: public CountDownLatch(int count) { }; //参数count为计数值 然后下面这3个方法是CountDownLatch类中最重要的方法: p…
java.util.concurrent CyclicBarrier简介 CyclicBarrier:可重用屏障/栅栏 类似于 CountDownLatch(倒计数闭锁),它能阻塞一组线程直到某个事件的发生. 与闭锁的关键区别在于,所有的线程必须同时到达屏障位置,才能继续执行. CountDownLatch 的计数器只能使用一次,而 CyclicBarrier 的计数器可以使用 reset() 方法重置 CountDownLatch 采用减计数方式,CyclicBarrier 采用加计数方式 C…
引导 要求:线程资源必须通过线程池提供,不允许在应用自行显式创建线程: 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题.如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗内存或者"过度切换"的问题. by <阿里巴巴Java手册> 线程池介绍 线程池概述   线程池,顾名思义是一个放着线程的池子,这个池子的线程主要是用来执行任务的.当用户提交任务时,线程池会创建线程去执行任务,若任务超过了核心线程数的时候,会在一个任务…
Posted by 微博@Yangsc_o 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 文章目录 摘要 forkjoin CountDownLatch CyclicBarrier Semaphore 参考 你的鼓励也是我创作的动力 摘要 本文主要简单介绍forkjoin.CountDownLatch.CyclicBarrier.Semaphore的常见用法: forkjoin 从JDK1.7开始,Java提供Fork/J…
信号量 其实本质上是锁,Lock是单锁,信号量是指定多把锁,也就是说通过信号量指定多个数线程可以访问相同资源,一般情况下读操作可以有多个,但写操作同时只有一个 信号量模块 semaphore # 使用起来和普通锁没 什么区别,但这个是比锁更加粗粒度锁,锁的是线程 # 在线程实例前加锁,把锁传递进线程,在线程结束时候释放锁 from threading import Thread, Semaphore from queue import Queue def add(chan, sem_lock):…
转自:http://www.kailing.pub/article/index/arcid/255.html 前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用FixedThreadPool还是CachedThreadPool其背后实现都是ThreadPoolExecutor.ThreadPoolExecutor是一个典型的缓存池化设计的产物,因为池子有…
看下组织结构: System.Object System.MarshalByRefObject System.Threading.WaitHandle System.Threading.Mutex System.Threading.Semaphore System.Threading.EventWaitHandle System.Threading.ManualResetEvent System.Threading.AutoResetEvent System.Object System.Thre…
前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己来自定义一个线程池,今天来学习一下ThreadPoolExecutor,然后结合使用场景定义一个按照线程优先级来执行的任务的线程池. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之ExecutorService线程池 Android线程管理之Threa…
Semaphore的作用是,限制线程通行的数量,如果线程进入时达到通行数量,便等待其它正在通行的线程释放. acquire()获取通行 release()释放通行 availablePermits()查看通行剩余次数 int drainPermits()缩减剩余通行次数为0,并返回缩减量 reducePermits(int)缩减通行次数为指定次数 boolean isFair()查看是否公平分配通行 boolean hasQueuedThreads()查看是否有线程在排队 int getQueu…
学习这个很长时间了一直没有去做个总结,现在大致总结一下并发包的线程池. 首先,任何代码都是解决问题的,线程池解决什么问题? 如果我们不用线程池,每次需要跑一个线程的时候自己new一个,会导致几个问题: 1,不好统一管理线程和它们的相互之间的依赖关系,尤其是有的程序要做的事情很多的时候,线程的处理就显得很杂乱,更雪上加霜的是,线程本身就是不可预期的,不是说先跑的线程就一直在后跑的线程前面,一旦形成复杂的依赖关系,也就会形成复杂的状态(由所有线程的状态共同决定). 2,效率低下,有可能你的每次跑的线…
百度百科:Semaphore,是负责协调各个线程, 以保证它们能够正确.合理的使用公共资源.也是操作系统中用于控制进程同步互斥的量. Semaphore常用的方法有两个WaitOne()和Release(),Release()的作用是退出信号量并返回前一个计数,而WaitOne()则是阻止当前线程,直到当前线程的WaitHandle 收到信号.这里我举一个例子让大家更容易理解:当我们这样实例化Semaphore时候 Semaphore sema = new Semaphore(x,y) 有一队人…
ThreadPoolExecutor是JDK自带的并发包对于线程池的实现,从JDK1.5开始,直至我所阅读的1.6与1.7的并发包代码,从代码注释上看,均出自Doug Lea之手,从代码上看JDK1.7几乎是重写了ThreadPoolExecutor的实现代码,JDK1.6的实现比较晦涩难懂,不便于理清作者的思路,故从JDK1.7的代码说起. ThreadPoolExecutor既然是一个线程池,那么所谓池子的概念和意义多半在于充分利用资源,线程池当然就是为了充分利用线程资源,即尽量减少新建和销…
thrift作为一个从底到上除去业务逻辑代码,可以生成多种语言客户端以及服务器代码,涵盖了网络,IO,进程,线程管理的框架,着实庞大,不过它层次清晰,4层每层解决不同的问题,可以按需取用,相当方便. +-------------------------------------------+ | Server | -- 服务器进程调度 | (single-threaded, event-driven etc) | +-----------------------------------------…
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是独占锁.对于独占锁而言,它每次只能有一个线程持有,而共享锁则不同,它允许多个线程并行持有锁,并发访问共享资源. 独占锁它所采用的是一种悲观的加锁策略,  对于写而言为了避免冲突独占是必须的,但是对于读就没有必要了,因为它不会影响数据的一致性.如果某个只读线程获取独占锁,则其他读线程都只能等待了,这种情况下就限…
线程池 线程池处理流程 核心线程池:创建新线程执行任务,需要获取全局锁 队列:将新来的任务加入队列 线程池:大于corePoolSize,并且队列已满,小于maxPoolSize,创建新的worker执行任务 线程池已满(达到max)处理策略:大于线程最大处理能力,大于maxPoolSize,选择拒绝策略 尽可能避免获取全局锁,corePoolSize就是这个作用,线程池开始处理任务,预热达到corePoolSize之后,将新来的任务放入队列 execute public void execut…
Semaphore类可以控制某个资源允许访问的线程数,Semaphore有命名式的,也有不命名的:如果不考虑跨进程工作,一般在代码中使用不命名方式即可. 信号量有点类似于等待句柄,某个线程如果调用了WaitOne方法,这个线程就会暂停,并且等待有可用的信号量时才会继续执行:某个线程调用Release方法,就会释放一个信号计数值,每调用一次就释放一个,如果想一次性释放N个信号,可以调用Release(int)重载,把要释放的数量传递给方法参数,但这个数值不能超过Semaphore实例化时所指定的最…