semaphore

Java Semaphore实现线程池任务调度

☆樱花仙子☆ 提交于 2020-04-26 06:36:30
关于Semaphore举例 以一个停车场运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。 在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。 信号量的特性如下: 信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。 在java中,还可以设置该信号量是否采用公平模式,如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。 JDK中定义如下: Semaphore(int permits, boolean fair)

JAVA 并发体系概览

安稳与你 提交于 2020-04-10 17:40:26
Java并发包主要有以下部分构成: 同步对象 主要提供多个线程以何种方式进行通信协作 执行器 管理多线程,提供线程运行入口 锁 控制线程访问资源的顺序 原子操作 对Java的基本类型进行了封装,对integer等这些包装类提供了原子操作 并发框架 为了简化并行编程的复杂性,Java或者其他公司定义的并发框架 以上对相关的类有一个大致的概览,下面主要大概的讲述一下同步对象的使用场景 Semaphore : 信号量:信号量通过计数器控制对共享资源的访问。如果计数器大于0,访问允许,如果为0,访问是拒绝的。计数器计数允许访问共享资源的许可证,因此,为了访问资源,线程必须获取信号量的访问许可。通常,为了使用信号量,希望访问共享资源的线程尝试取得许可。如果信号量的计数器大于0,就表明线程取得了许可证,这会导致信号量的计数减小;否则线程会被阻塞,直到能够获取许可证为止。当线程不需要访问共享资源时,释放许可证,从而增大信号量的计数。如果还有另外的一个线程正在等待许可证,该线程将在这一刻取得许可证 CountDownLatch : 有时候希望线程进行等待,直到发生一个或多个事件为止。为了处理这类情况,并发API提供了CountDownLatch类。CountDownLatch在初始创建时带有时间数量计数器,在释放锁存器之前,必须发生指定数量的时间。每次发生一个事件时,计数器递减。当计数器达到0时

线程之Semaphore之事例

删除回忆录丶 提交于 2020-04-05 15:59:36
概述 为了提高接口的响应速度,可以使用 ThreadPoolExecutor + Runnable 或者 ThreadPoolExecutor 并发调用 技术来并行执行task。但是ThreadPoolExecutor有个特点,就是当core线程不足以应付请求的时候,会将task加入到队列中。一旦使用队列,那么就可能出现队列爆掉或者队列导致的内存溢出问题。 为了尽快提供接口响应速度,但是又不想使用队列特性的话。可以使用信号量来做到。 Semaphore信号量管理着一组许可,在执行操作时需要首先获得许可,并在使用后释放许可。如果已经没有许可了, acquire方法将一直阻塞,直到有许可。 信号量简单例子 ThreadPoolExecutor中使用信号量 在ThreadPoolExecutor中,我们在定义core线程参数的时候,比如定义为10个,那么使用信号量的时候,初始化参数也设置为10. Semaphore<Integer> sem= new Semaphore<>(10); ThreadPoolExecutor中,如果不想用到队列, 就必须保证线程池中始终只有core线程在工作 。那么当请求太多,core线程处理不过来的时候,用信号量进行阻塞, 保证只有当core线程的某些线程执行完后,阻塞才解开。 这里使用JAVA并发编程一书中的例子来说明信号量的基本用法。 public

Grand Central Dispatch (GCD) 转

北城余情 提交于 2020-04-03 05:31:34
GCD是异步执行任务的技术之一。 GCD使用很简洁的记述方法,实现了极为复杂繁琐的多线程编程。 dispatch_async(queue, ^{ //长时间处理 //例如AR用动画识别 //例如数据库访问 //长时间处理结束,主线程使用该处理结果 dispatch_async( dispatch_get_main_queue(), ^{ //只在主线程可以执行的处理 //例如用户界面更新 }); }); 在NSObject中,提供了两个实例方法来实现简单的多线程技术:performSelectorInBackground:withObject performSelectorOnMainThread。 我们也可以改用performSelector系方法来实现前面使用的GCD。 //NSObject performSelectorInBackground:withObject:方法中执行后台线程 - (void)launchThreadByNSObject_performSelectorInBackground_withObject { [self performSelectorInBackground:@selector(doWork) withObject:nil]; } //后台线程处理方法 - (void)doWork { @autoreleasepool{ //长时间处理,

Grand Central Dispatch(GCD)详解

蓝咒 提交于 2020-04-03 05:31:01
概述 GCD 是苹果异步执行任务技术,将应用程序中的线程管理的代码在系统级中实现。开发者只需要定义想要执行的任务并追加到适当的 Dispatch Queue 中, GCD 就能生成必要的线程并计划执行任务。由于线程管理是作为系统的一部分来实现的,因此可以统一管理,也可执行任务,这样比以前的线程更有效率。 GCD的使用 dispatch_sync与dispatch_async dispatch_sync synchronous 同步,一旦调用 dispatch_sync 方法,那么指定的处理 (block) 追加到指定 Dispatch Queue 中在执行结束之前该函数都不会返回,也就是说当前的线程会阻塞,等待 dispatch_sync 在指定线程执行完成后才会继续向下执行。 dispatch_async synchronous异步,一旦调用 dispatch_async 方法,那么指定的处理 (block) 追加到指定的 Dispatch Queue 中, dispatch_async 不会做任何等待立刻返回,当前线程不受影响继续向下执行。 注意 使用 dispatch_sync 容易造成死锁,一般情况下应该使用 dispatch_async ,例如 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch

iOS多线程——GCD篇

左心房为你撑大大i 提交于 2020-04-03 05:25:54
什么是GCD GCD是苹果对多线程编程做的一套新的抽象基于C语言层的API,结合Block简化了多线程的操作,使得我们对线程操作能够更加的安全高效。 在GCD出现之前Cocoa框架提供了NSObject类的 performSelectorInBackground:withObject performSelectorOnMainThread 方法来简化多线程编程技术。 GCD可以解决以下多线程编程中经常出现的问题: 1.数据竞争(比如同时更新一个内存地址) 2.死锁(互相等待) 3.太多线程导致消耗大量内存 在iOS中,如果把需要消耗大量时间的操作放在主线程上面,会妨碍主线程中被称为RunLoop的主循环的执行,从而导致不能更新用户界面、应用程序的画面长时间停滞等问题。 Dispatch Queue Dispatch Queue是GCD中对于任务的抽象队列(FIFO)执行处理。 queue分为两种, SERIAL_DISPATCH_QUEUE           等待现在执行中处理结束 CONCURRENT_DISPATCH_QUEUE       不等待现在执行中处理结束 换句话说也就是 SERIAL_DISPATCH_QUEUE 是串行,CONCURRENT_DISPATCH_QUEUE是并行。 具体到线程上,就是SERIAL_DISPATCH

CountDownLatch、CyclicBarrier和Semaphore

不羁的心 提交于 2020-04-02 09:37:54
一.CountDownLatch用法 CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。 CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。 当我们调用一次CountDownLatch的countDown方法时,N就会减1,CountDownLatch的await会阻塞当前线程,直到N变成零。由于countDown方法可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,你只需要把这个CountDownLatch的引用传递到线程里。 其他方法 如果有某个解析sheet的线程处理的比较慢,我们不可能让主线程一直等待,所以我们可以使用另外一个带指定时间的await方法,await(long time, TimeUnit unit): 这个方法等待特定时间后,就会不再阻塞当前线程。join也有类似的方法。 注意:计数器必须大于等于0,只是等于0时候,计数器就是零,调用await方法时不会阻塞当前线程。CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部计数器的值

iOS-关于GCD信号量那些事儿

随声附和 提交于 2020-03-30 19:55:48
随便说说 其实GCD大家都有接触过,也不在解释GCD是什么,为什么突然想说信号量问题,最近这几次面试,当我问到面试者怎么处理多个请求完成后的一系列操作时,有的说造一个临时变量的做追加,其实这样可以,也算是信号量的基本逻辑,有的说用线程做延时操作,怎么延时,怎么操作说的不清楚,有少部分会提到GCD信号量,但是可能说不出来怎么操作,通过信号量的增加与递减,进行网络的并发请求,最后再做网络请求完成后的最终处理;其实实际上大家在做的时候,在网上一搜,基本都能找到; GCD信号量的应用场景,一般是控制最大并发量,控制资源的同步访问,如数据访问,网络同步加载等 简单聊聊 ///创建 dispatch_semaphore_create() ///增加 dispatch_semaphore_signal() ///减去 dispatch_semaphore_wait() 下面用简单的栗子模拟多个网络请求,再进行最终的操作 //创建信号量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //创建队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); //创建线程组 dispatch_group_t group = dispatch_group_create(

面试刷题19:并发工具包有哪些工具?

喜夏-厌秋 提交于 2020-03-30 16:17:34
java.util.concurrent包提供了大量的并发工具。 大家好,我是李福春,今天的题目是: java提供的并发工具有哪些? 答:java.util.concurrent工具包中提供的工具分4大类。 一, 同步工具,CountDownLatch, CyclicBarrier , Semaphore ; 二, 并发安全容器, ConcurrentHashMap,ConcurrentSkipListMap, CopyOnWriteArrayList,CopyOnWriteArraySet; 三,并发安全队列,主要用在线程池上,ArrayBlockingQueue,SynchronousQueue,PriorityBlockingQueue; 四,并发线程池executor框架; 同步工具 semaphore 信号量,设置并发访问的线程数量。 一般要结对使用: try{s.acquire();}finally{s.release()} package org.example.mianshi.synctool; import java.util.concurrent.Semaphore; /** * 创建日期: 2020/3/30 14:24 * 描述: 信号量应用 * * @author lifuchun */ public class SemaphoreApp { public

线程同步(互斥锁与信号量的作用与区别)

感情迁移 提交于 2020-03-28 03:59:40
“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁和信号量会同时使用的” 也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务 并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而线程互斥量则是“锁住某一资源”的概念,在锁定期间内,其他线程无法对被保护的数据进 行操作。在有些情况下两者可以互换。 两者之间的区别: 作用域 信号量: 进程间或线程间(linux仅线程间的无名信号量pthread semaphore) 互斥锁: 线程间 上锁时 信号量: 只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait使得线程阻塞,直到sem_post释放后value值加一,但是sem_wait返回之前还是会将此value值减一 互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源 以下是信号灯(量