优先级队列

Heapsort 和 priority queue

怎甘沉沦 提交于 2020-04-18 04:49:28
一、二叉堆含义及属性: 堆(heap)亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因而实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。同垃圾收集存储的堆含义不同。 表示堆的数组A有两个属性: A.length : 代表A数组的元素个数; A.heapsize : 代表A数组中 属于堆元素个数。有时候(排序时),数组A的部分元素不属于堆。刚开始建堆的是偶,A.heapsize = A.length,排序时,每次从堆顶取出最大值,A.heapsize递减,直至排序完成. 下图是一个建好后的二叉堆: 从图中可知,已知某节点的索引值i,可以轻松获取其对应父节点,左,右子节点的索引值。有: Parent(i) return i/2; 或者 return i >> 1; Left(i) return i*2; 或者 return i << 1; Right(i) return i*2+1; 或者 return (i << 1) + 1; 二叉堆分两种: 最大堆,最小堆,均遵循堆属性。最大堆,每个节点i满足: A[Parent(i)] ≥ A[i]

java中线程队列BlockingQueue的用法

試著忘記壹切 提交于 2020-04-07 11:09:48
在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。 [ @more @] 认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示: 从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出; 常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种)   先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。   后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。 多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程,利用队列的方式来传递数据,就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内

concurrent包的数据结构

ぐ巨炮叔叔 提交于 2020-04-07 03:50:47
concurrent包的数据结构:阻塞的结构都是用lock加锁(lock会休眠锁),非阻塞是用CAS直接for循环加入。 结构简介 名称 功能 组成 原子量 AtomicBoolean Unsafe+==volatile int value== AtomicInteger Unsafe+==volatile int value== AtomicIntegerArray Unsafe+==final int[] array== AtomicLong Unsafe+==volatile long value== AtomicLongArray Unsafe+==final int[] array== 名称 功能 组成 阻塞队列 ==继承: BlockingQueue 接口== ArrayBlockingQueue 数组+lock LinkedBlockingQueue 链表+lock PriorityBlockingQueue**(优先级队列)** 自定义哪个队列先出 数组+lock DelayQueue (时间队列) 队列中每个元素都有个过期时间,并且队列是个优先级队列,当从队列获取元素时候,只有过期元素才会出队列 PriorityQueue(优先级队列)+lock SynchronousQueue 一个不存储元素的阻塞队列 阻塞队列(双端) ==继承: BlockingDeque

OC开发_整理笔记——多线程之GCD

泄露秘密 提交于 2020-04-03 10:22:10
一、进程和线程     二、各种队列!   1、GCD:Grand Central Dispatch   2、串行队列(Serial)     你 可以创建 任意个数的串行队列,每个队列依次执行添加的任务, 一个队列同一时刻只能执行一个任务 (串行),但是各个队列之间不影响,可以并发执行。每个队列中的任务运行在一个由各自串行队列    维护的独立线程上, 一个队列中只有一个线程 。   3、并行队列(Concurrent)     并行队列是 不允许自己创建 的,系统中存在三个不同优先级的并行队列。并行队列依旧按照任务添加的顺序启动任务,但是,后一个任务无须等待前一个任务执行完毕,而是启动第一个任务后,立即启动    下一个任务。至于同一时刻允许同时运行多少个任务由 系统决定 。任务各自运行在并行队列为他们提供的独立线程上, 并行队列中同时运行多少个任务,就必须维护多少个线程 。   4、主调度队列(main dispatch queue)     主调度队列中的任务运行在应用程序 主线程 上,所以,如果你要修改应用程序的界面,他是唯一的选择   5、全局队列(苹果为了方便多线程的设计,提供一个全局队列,供 所有的APP共同使用 ) 三、队列的任务处理   1、串行队列(✅ DISPATCH_QUEUE_SERIAL )的同步任务和异步任务:dispatch_sync 和

GCD简介

谁说胖子不能爱 提交于 2020-04-03 05:22:05
本文转自 http://www.cnblogs.com/sell/archive/2013/02/06/2905772.html GCD ( Grand Central Dispatch ) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式。 在Mac OS X 10.6和IOS 4.0之后开始支持GCD。 使用GCD的一个理由就是方便。回想一下以前的多线程编程,我们会把异步调用的代码放到另外的一个函数中,并通过NSThread开启新线程来启动这段代码。 这种跳来跳去的流程对于复杂的逻辑简直就是一场灾难。更糟糕的是,调用线程时的环境对异步代码是不可见的,如果我们需要当时的临时变量的话只有两个选择: 保存到类成员变量中或者作为参数传递过去。前者会造成很多莫名奇妙的无关类成员,而后者的功能过于有限。 GCD相对来说是一种更优雅的方式,看如下代码: NSString* parameter = [self getSomeParameter]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSString* result = [self fetchResultFromWebWithParameter:parameter];

BlockingQueue队列

孤街浪徒 提交于 2020-04-01 06:30:24
1.BlockingQueue定义的常用方法如下 抛出异常 特殊值 阻塞 超时 插入 add(e) offer(e) put(e) offer(e,time,unit) 移除 remove() poll() take() poll(time,unit) 检查 element() peek() 不可用 不可用 1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回异常 2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false. 3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续. 4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null 5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止 其中:BlockingQueue 不接受 null

深入浅出Java(Android )线程池ThreadPoolExecutor

血红的双手。 提交于 2020-03-30 15:26:01
前言 关于线程池 在Java/Android开发中,设计到并发的请求,那基本上是离不开线程池了。用线程池的好处: 1、减少线程频繁创建、销毁的开销; 2、好控制并发量,降低OOM的可能,至于原因文中会说; 3、提高程序的响应速度,因为可以省去部分创建的过程; 要不要深度学习线程池 对于服务端的同学来说应该会比较重视这一块,因为需要做高并发;而移动端的同学可能比较容易忽略这一块。有些人觉得平时也用不到,移动端没有那么大并发量,或者说第三方框架中已经完成了,比如 OkHtttp ; 其实只能说有这种想法的同学还没有遇到大一点的项目或者说没有太多多线程优化的经验。 如果你真的遇到了这种项目瓶颈,你连线程池的运行原理都不知道,那又如何解决项目问题呢? 如果你要寻求一份中高级开发工程师的工作,那线程池是基本是必问题目之一,而且还要有一定深度。 如何深度学习线程池 这也是我们今天的重点,本文将从下面几点带大家快速掌握线程池的要点: 1、从API使用到原码解析,基于JDK1.8版本; 2、从源码阅读(深入)中总结出(浅出)线程池工作原理; 3、对应用场景的分析以及异常处理 预览 线程池类图.png 先对线程池的部分核心类/接口做个简介,大家有个印象就好。 Executor接口 public interface Executor { /** * 就一个方法,用来执行线程任务的

并发编程相关面试题四

倖福魔咒の 提交于 2020-03-28 12:34:17
一、Java开发中用过哪些锁 1、乐观锁   乐观锁顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的   乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升;     乐观锁在Java中的使用,是无锁编程,常常采用的是CAS算法,典型的例子就是原子类,通过CAS自旋实现原子操作的更新。 2、悲观锁   悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。比如Java里面的同步原语synchronized关键字的实现就是悲观锁。   悲观锁适合写操作非常多的场景;   悲观锁在Java中的使用,就是利用各种锁; 3、独享锁   独享锁是指该锁一次只能被一个线程所持有。   独享锁通过AQS来实现的,通过实现不同的方法,来实现独享锁。   对于Synchronized而言,当然是独享锁。 4、共享锁   共享锁是指该锁可被多个线程所持有。  

IOS多线程知识总结/队列概念/GCD/串行/并行/同步/异步

寵の児 提交于 2020-03-28 04:03:41
进程 :正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间; 线程 :线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程。 队列 : dispatch_queue_t,一种先进先出的数据结构, 线程的创建和回收不需要程序员操作,由队列负责。    串行队列 :队列中的任务只会顺序执行(类似跑步)        dispatch_queue_t q = dispatch_queue_create(“....”, dispatch_queue_serial);    并行队列 :队列中的任务通常会并发执行(类似赛跑)       dispatch_queue_t q = dispatch_queue_create("......", dispatch_queue_concurrent);    全局队列 :是 系统开发 的,直接拿过来(get)用就可以;与并行队列类似,但调试时,无法确认操作所在队列       dispatch_queue_t q = dispatch_get_global_queue(dispatch_queue_priority_default, 0);    主队列 :每一个应用程序对应唯一一个主队列,直接get即可;在多线程开发中,使用主队列更新UI        dispatch_queue

基于redis的延迟消息队列设计

怎甘沉沦 提交于 2020-03-28 02:55:12
介绍 延迟队列,顾名思义它是一种带有延迟功能的消息队列。 那么,是在什么场景下我才需要这样的队列呢? 很多时候我们会有延时处理一个任务的需求,比如说: 2个小时后给用户发送短信。 15分钟后关闭网络连接。 2分钟后再次尝试回调。 下面我们来分别探讨一下几种实现方案: 1、Java中的DelayQueue Java中的DelayQueue位于java.util.concurrent包下,本质是由PriorityQueue和BlockingQueue实现的阻塞优先级队列。 见《 延时队列:Java中的DelayQueue 》 2、使用Redis实现 前文我们看到,可以通过优先级队列来实现延迟队列的功能。Redis提供了很多数据结构,其中的zset是一种有序的数据结构;我们可以通过Redis中的zset来实现一个延迟队列。 基本的方法就是使用时间戳作为元素的score存入zset。 redis> ZADD delayqueue <future_timestamp> "messsage" 获取所有已经“就绪”的message,并且删除message。 redis> MULTI redis> ZRANGEBYSCORE delayqueue 0 <current_timestamp> redis> ZREMRANGEBYSCORE delayqueue 0 <current