一种数据传输装置和方法
【专利摘要】本发明公开了一种数据传输装置和方法,其中数据传输装置包括:数据存储器,适于以循环队列存储数据,循环队列以数组结构实现,具有头索引和尾索引,循环队列中的每个元素对应一个序列号;写接口,适于接收生产者线程的写入指令向循环队列写入数据,包括读取头索引并将其赋值给第一索引,通过判断第一索引指向的元素的序列号与第一索引的大小,执行相应的数据写入操作;读接口,适于接收消费者线程的读取指令从循环队列读取数据,包括读取尾索引并将其赋值给第二索引,通过判断第二索引指向的序列号减1的值与第二索引的大小,执行相应的数据读取操作;其中,头索引、尾索引、序列号、第一索引和第二索引均是原子对象。
【专利说明】
_种数据传输装置和方法
技术领域
[0001 ]本发明涉及数据通信领域,特别涉及一种数据传输装置和方法。
【背景技术】
[0002] 随着计算机应用的日益广泛和深入,与数据交互和传输相关的技术也不断发展和 进步。在数据通信的过程中,当使用多线程并发处理数据时,如果直接处理,需要在并发请 求的过程中使用互斥锁来保持数据的一致性。尤其在涉及到大量的请求时,使用原有的互 斥锁机制难以保证这些请求之间的有序并发处理,时间消耗较大。以多线程并发对同一文 件记录日志为例,如果直接写入文件,由于同一进程共用文件表,必须对写入操作加锁,此 时并发写入调用在逻辑上转化为实际的串行文件写入,而线程同步本身也会消耗时间,导 致在并发较大时线程同步的时间消耗甚至大于日志写入本身的时间消耗。
[0003] 然而,即使通过队列作为媒介,用户线程作为生产者构造数据处理任务并向队列 写入,线程池作为消费者从队列读取数据处理任务并执行,利用队列对任务进行传输来实 现异步数据处理,但多线程下的队列操作仍需要加锁,时间上的过多消耗难以消除。
【发明内容】
[0004] 为此,本发明提供一种数据传输的方案,以力图解决或者至少缓解上面存在的问 题。
[0005] 根据本发明的一个方面,提供一种数据传输装置,包括:数据存储器,适于以循环 队列存储数据,循环队列以数组结构实现,具有头索引和尾索引,循环队列中的每个元素对 应一个序列号,序列号初始化为元素对应的数组下标;写接口,适于接收一个或多个生产者 线程的写入指令,根据写入指令向循环队列写入数据,向循环队列写入数据包括读取头索 引并将其赋值给第一索引,通过判断第一索引指向的元素的序列号与第一索引的大小,执 行相应的数据写入操作;读接口,适于接收一个或多个消费者线程的读取指令,根据读取指 令从循环队列读取数据,从循环队列读取数据包括读取尾索引并将其赋值给第二索引,通 过判断第二索引指向的序列号减1的值与第二索引的大小,执行相应的数据读取操作;其 中,头索引、尾索引、序列号、第一索引和第二索引均是原子对象。
[0006] 可选地,在根据本发明的数据传输装置中,写接口进一步适于:当序列号等于第一 索引时,头索引增加1,将待写入数据写入第一索引指向的元素中,序列号增加1。
[0007] 可选地,在根据本发明的数据传输装置中,写接口进一步适于:当序列号大于第一 索引时,重新向循环队列写入数据,当重写次数达到预设的最大重写次数时,判断数据写入 失败。
[0008] 可选地,在根据本发明的数据传输装置中,写接口进一步适于:当序列号小于第一 索引时,判断当前循环队列已满,数据写入失败。
[0009] 可选地,在根据本发明的数据传输装置中,读接口进一步适于:当序列号减1的值 等于第二索引时,尾索引增加1,将待读取数据从第二索引指向的元素中读取出来,序列号 增加数组长度再减去1。
[0010] 可选地,在根据本发明的数据传输装置中,读接口进一步适于:当序列号减1的值 大于第二索引时,重新从循环队列读取数据,当重写次数达到预设的最大重读次数时,判断 数据读取失败。
[0011] 可选地,在根据本发明的数据传输装置中,读接口进一步适于:当序列号减1的值 小于第二索引时,判断当前循环队列已空,数据读取失败。
[0012] 可选地,在根据本发明的数据传输装置中,数据包括日志任务。
[0013] 可选地,在根据本发明的数据传输装置中,生产者线程在日志任务写入失败时,执 行日志任务,生成日志文件。
[0014] 可选地,在根据本发明的数据传输装置中,消费者线程在日志任务读取成功时,执 行日志任务,生成日志文件。
[0015] 可选地,在根据本发明的数据传输装置中,读接口进一步适于:当日志任务读取失 败时,等待预定时间后,重新从循环队列读取日志任务。
[0016] 根据本发明的又一个方面,提供一种数据传输方法,适于对以循环队列存储数据 的数据存储器进行写入和读取操作,其中循环队列以数组结构实现,具有头索引和尾索引, 循环队列中的每个元素对应一个序列号,序列号初始化为元素对应的数组下标,方法包括: 接收一个或多个生产者线程的写入指令,根据写入指令向循环队列写入数据,向循环队列 写入数据包括读取头索引并将其赋值给第一索引,通过判断第一索引指向的元素的序列号 与第一索引的大小,执行相应的数据写入操作;接收一个或多个消费者线程的读取指令,根 据读取指令从循环队列读取数据,从循环队列读取数据包括读取尾索引并将其赋值给第二 索引,通过判断第二索引指向的元素的序列号减1的值与第二索引的大小,执行相应的数据 读取操作;其中,头索引、尾索引、序列号、第一索引和第二索引均是原子对象。
[0017] 可选地,在根据本发明的数据传输方法中,数据写入操作包括:如果序列号等于第 一索引,则头索引增加1,将待写入数据写入第一索引指向的元素中,序列号增加1。
[0018] 可选地,在根据本发明的数据传输方法中,数据写入操作包括:如果序列号大于第 一索引,则重新向循环队列写入数据,如果重写次数达到预设的最大重写次数,则判断数据 写入失败。
[0019] 可选地,在根据本发明的数据传输方法中,数据写入操作包括:如果序列号小于第 一索引,则判断当前循环队列已满,数据写入失败。
[0020] 可选地,在根据本发明的数据传输方法中,数据读取操作包括:如果序列号减1的 值等于第二索引,则尾索引增加1,将待读取数据从第二索引指向的元素中读取出来,序列 号增加数组长度再减去1。
[0021 ]可选地,在根据本发明的数据传输方法中,数据读取操作包括:如果序列号减1的 值大于第二索引,则重新从循环队列读取数据,如果重写次数达到最大重读次数,则判断数 据写入失败。
[0022] 可选地,在根据本发明的数据传输方法中,数据读取操作包括:如果序列号减1的 值小于第二索引,则判断当前循环队列已空,数据读取失败。
[0023] 可选地,在根据本发明的数据传输方法中,数据包括日志任务。
[0024] 可选地,在根据本发明的数据传输方法中,还包括:如果日志任务写入失败,则生 产者线程执行日志任务,生成日志文件。
[0025] 可选地,在根据本发明的数据传输方法中,还包括:如果日志任务读取成功,则消 费者线程执行日志任务,生成日志文件。
[0026] 可选地,在根据本发明的数据传输方法中,数据读取操作还包括:如果日志任务读 取失败,则等待预定时间后,重新从循环队列读取日志任务。
[0027] 根据本发明的数据传输的技术方案,对以循环队列存储数据的数据存储器进行写 入和读取操作,每个队列元素具有一个序列号,接收一个或多个生产者线程的写入指令来 向循环队列写入数据,同时接收一个或多个消费者线程的读取指令来从循环队列读取数 据,生产者线程和消费者线程以一个无锁循环队列为媒介进行数据传输,借助队列元素上 的序列号,在入/出队时可无锁的实现"队满/空"、"写/读成功"、"写/读冲突"三种状态的判 断,而且通过对序列号和队列长度减1的值进行"与"运算,相当于将循环队列展开为无数个 先入先出队列,实现队列的循环使用即循环队列,并支持多线程在不加互斥锁的情况下同 时进行数据写入/读取操作,消除了因加锁机制造成的阻塞等待,降低了数据处理的平均响 应时延。
【附图说明】
[0028] 为了实现上述以及相关目的,本文结合下面的描述和附图来描述某些说明性方 面,这些方面指示了可以实践本文所公开的原理的各种方式,并且所有方面及其等效方面 旨在落入所要求保护的主题的范围内。通过结合附图阅读下面的详细描述,本公开的上述 以及其它目的、特征和优势将变得更加明显。遍及本公开,相同的附图标记通常指代相同的 部件或元素。
[0029] 图1示出了根据本发明的一个实施例的数据存取装置100的示意图;
[0030]图2(a)_(e)示出了根据本发明的一个实施例的以数组结构实现的循环队列进行 数据传输过程中队列状态的示意图;
[0031] 图3示出了根据本发明的一个实施例的数据传输方法中向循环队列写入数据的方 法300的流程图;以及
[0032] 图4示出了根据本发明的一个实施例的数据传输方法中从循环队列读取数据的方 法400的流程图。
【具体实施方式】
[0033] 下面将参照附图更详细地描述本公开的示例性实施例。虽然附图中显示了本公开 的示例性实施例,然而应当理解,可以以各种形式实现本公开而不应被这里阐述的实施例 所限制。相反,提供这些实施例是为了能够更透彻地理解本公开,并且能够将本公开的范围 完整的传达给本领域的技术人员。
[0034] 图1示出了根据本发明的一个实施例的数据存取装置100的示意图。如图1所述,该 装置包括数据存储器110、写接口 120和读接口 130。其中,数据存储器110适于以循环队列存 储数据,循环队列以数组结构实现,具有头索引和尾索引,循环队列中的每个元素对应一个 序列号,序列号初始化为元素对应的数组下标。其中,头索引、尾索引和序列号均是原子对 象。采用原子对象的意义在于,可以保证在赋值操作之前的所有内存操作不会被重排序到 赋值操作之后,即避免了处理同一元素时因为指令重排而造成异常结果。在本实施例中,实 现循环队列的数组以buf f er表示,数组长度以1 en表示,其值为8,包括buf f er [ 0 ]至buf fer [7]的8个元素,头索引以head表示,尾索引以tail表示,head和tail在初始状态均指向循环 队列的第一个元素 buf fer [0],循环队列中的每个元素对应一个序列号seq,buf fer [0]至 buffer[7]的序列号初始化后依次为0、1、2、3、4、5、6和7。
[0035] 图2(a)示出了根据本发明的一个实施例的以数组结构实现的循环队列初始状态 的示意图。如图2所示,初始化后,头索引head和尾索引tail均指向第一个元素 buffer[0], 其中0至7分别表示对应元素的序列号seq。
[0036] 写接口 120适于接收一个或多个生产者线程的写入指令,每接收到一条写入指令, 则根据该写入指令向循环队列写入数据,包括读取头索引并将其赋值给第一索引,通过判 断第一索引指向的元素的序列号与第一索引的大小,执行相应的数据写入操作,其中,第一 索引是原子对象。写接口 120进一步适于当序列号等于第一索引时,头索引增加1,将待写入 数据写入第一索引指向的元素中,序列号增加1;当序列号大于第一索引时,重新向循环队 列写入数据,当重写次数达到预设的最大重写次数时,判断数据写入失败;当序列号小于第 一索引时,判断当前循环队列已满,数据写入失败。在本实施例中,对如图2(a)所示的循环 队列执行数据写入操作。第一索引以P〇sl表示,读取head的值并将其赋值给posl,当前head 的值为0,则口〇81的值为0。而口〇81指向的元素为131^€61'|^〇81&(1611-1)],其中口〇81&(1611-1) 表示将posl和len-Ι的值转化为二进制后进行与操作,得到的结果转化为十进制后作为数 组buf fer的下标。此时,pos 1的值为0,转换成二进制表示为0000,len-Ι的值为7,转化成二 进制表示为0111,则0000&0111得到的值为〇〇〇〇,转化为十进制后为〇,得到当前posl指向的 元素为buf fer [0],其对应的seq为0。由于buf fer [0]对应的seq与posl相等,因此将head的 值增加1,并将待写入数据写入posl指向的元素 buf fer [0]中,而buf fer [0]对应的seq也增 加1〇
[0037] 由于在进行数据写入操作时,存在多个生产者线程同时写入的情况,此时各生产 者线程需要对循环队列中的元素进行抢占。实际上,在对head进行加1的操作时,是使用 try_compare(head,posl,posl+l)函数来进行处理的。其中,try_compare(head,posl,posl + 1)函数是原子比较交换函数。当执行该函数时,如果head = posl,则说明在执行函数之前 没有进行数据写入操作,则将P〇s 1+1的值赋值给head,pos 1的值保持不变,实现了对head加 1的操作。各生产者线程均尝试执行1^7_(3011^^代(1163(14〇814〇81 + 1)函数来对1163(1进行加 1操作,但只可能存在一个生产者线程成功,该成功使得head增加1的生产者线程抢占到 buff er[0]后写入数据。图2(b)示出了根据本发明的一个实施例的成功写入一个数据后的 循环队列的队列状态示意图。如图2(b)所示,此时head的值为1,指向的元素为buffer[l], buff er[0]对应的seq的值为1。
[0038] 在上述各生产者线程抢占元素 bUffer[0]的过程中,对抢占失败的生产者线程而 言,此时的buff er[0]对应的序列号seq的值为1,而抢占失败的生产者线程尚未重读head的 值来重新向循环队列中写入数据,使得posl的值并未更新而仍然为0,由于 Seq>p〇Sl,因此 上述失败的生产者线程重新读取head的值来继续尝试写入数据,并重写次数增加1。一般预 设最大重写次数为20次,如果生产者线程对数据的重写次数达到预设的最大重写次数,则 判断数据写入失败。
[0039] 图2(c)示出了根据本发明的一个实施例的循环队列已满的队列状态示意图。如图 2 (c)所示,当前循环队列已满,此时元素 buffer [0]至buffer [7]对应的序列号seq分别为1、 2、3、4、5、6、7和8。而在生产者线程抢占131^€61'[7]时,1:巧_(3〇11^^代(1163(1,口〇81,口〇81+1)函 数对head执行了加1的操作,使得head的值更新为8。而此时抢占 buffer [7]失败的生产者线 程重新尝试写入数据,读取head的值并赋值给posl,而posl指向的元素 buffer[posl&(len-1)]为131^€61'[1000&0111],即为131^€61'[0]。头索引1163(1重新指向了循环队列的第一个元 素,实现了逻辑上的循环结构。判断buffer [0]对应的seq与posl的大小,此时,seq的值为1, posl的值为8,则Seq〈p〇sl,判断循环队列已满,数据写入失败。
[0040] 读接口 130适于接收一个或多个消费者线程的读取指令,每接收到一条读取指令, 则根据读取指令从循环队列读取数据,包括读取尾索引并将其赋值给第二索引,通过判断 第二索引指向的序列号减1的值与第二索引的大小,执行相应的数据读取操作,其中,第二 索引为原子对象。读接口 130进一步适于当序列号减1的值等于第二索引时,尾索引增加1, 将待读取数据从第二索引指向的元素中读取出来,序列号增加数组长度再减去1;当序列号 减1的值大于第二索引时,重新从循环队列读取数据,当重写次数达到预设的最大重读次数 时,判断数据读取失败;当序列号减1的值小于第二索引时,判断当前循环队列已空,数据读 取失败。在本实施例中,对如图2(c)所示的循环队列执行数据读取操作。第二索引以pos2表 示,读取tail的值并将其赋值给pos2,当前tail的值为0,则pos2的值为0。而pos2指向的元 素为131^€61'|^082&(1611-1],其中口082&(1611-1)表示将口082和1611-1的值转化为二进制后进 行与操作,得到的结果转化为十进制后作为数组buffer的下标。此时,pos2的值为0,转换成 二进制表示为〇〇〇〇,len-l的值为7,转化成二进制表示为0111,则0000&0111得到的值为 〇〇〇〇,转化为十进制后为0,得到当前p〇s2指向的元素为buffer[0],其对应的seq为1。由于 buffer[0]对应的seq减1的值与pos2相等,因此将tail的值增加1,并将待读取数据从pos2 指向的元素 buffer [0]中读取出来,而buffer [0]对应的seq增加 len再减去1。
[0041] 由于在进行数据读取操作时,存在多个消费者线程同时读取的情况,此时各消费 者线程需要对循环队列中的元素进行抢占。实际上,在对tail进行加1的操作时,是使用 try_compare (tai 1,pos2,pos2+l)函数来进行处理的。其中,try_compare (tai 1,pos2,pos2 + 1)函数是原子比较交换函数。当执行该函数时,如果tail =pos2,则说明在执行函数之前 没有进行数据读取操作,则将P〇s2+l的值赋值给tail,pos2的值保持不变,实现了对tail加 1的操作。各消费者线程均尝试执行1^7_〇011^^代(丨3;[14082 4082+1)函数来对丨3;[1进行加 1操作,但只可能存在一个消费者线程成功,该成功使得tail增加1的消费者线程抢占到 buff er[0]后读取数据。图2(d)示出了根据本发明的一个实施例的成功读取一个数据后的 循环队列的队列状态示意图。如图2(d)所示,此时tail的值为1,指向的元素为buffer[l], buff er[0]对应的seq的值为8。
[0042] 在上述各消费者线程抢占元素 bUffer[0]的过程中,对抢占失败的消费者线程而 言,此时的buff er[0]对应的序列号seq的值为8,而抢占失败的消费者线程尚未重读tail的 值来重新从循环队列中读取数据,使得P〇s2的值并未更新而仍然为0,由于 Seq-l>p〇s2,因 此上述失败的消费者线程重新读取tail的值来继续尝试读取数据,并将重读次数增加1。一 般预设最大重读次数为20次,如果消费者线程对数据的重读次数达到预设的最大重读次 数,则判断数据读取失败。
[0043] 图2(e)示出了根据本发明的一个实施例的循环队列已空的队列状态示意图。如图 2 (e)所示,当前循环队列已空,此时元素 buffer [0]至buffer [7]对应的序列号seq分别为8、 9、10、11、12、13、14和15。而在消费者线程抢占 bufTer[7]时,try_compare(tail,pos2,pos2 + 1)函数对tail执行了加1的操作,使得tail的值更新为8。而此时抢占 buffer [7]失败的消 费者线程重新尝试读取数据,读取tail的值并赋值给pos2,而pos2指向的元素 buffer [pos2&(len_l)]为buffer[ 1000&0111],即为buffer[0]。尾索引 tail重新指向了循环队列 的第一个元素,实现了逻辑上的循环结构。判断buffer[0]对应的seq减1的值与pos2的大 小,此时,seq的值为8,pos2的值为8,则seq_l〈pos2,判断循环队列已空,数据读取失败。
[0044] 至此,循环队列中的元素中均写入和读取数据一次,头索引head和尾索引tail的 值均为8,且均指向循环队列的第一个元素 bUffer[0],完成了一次回绕,实现了无锁循环队 列。
[0045] 在本发明的实施例中,传输的数据可以是日志任务。当生产者线程在日志任务写 入失败时,直接调用日志写入API,执行日志写入函数将日志数据写入文件,以生成日志文 件。当消费者线程在日志任务读取成功时,消费者线程调用日志写入函数执行写入操作,生 成日志文件。其中,考虑到日志这一特殊的应用场景,多线程并发执行日志任务,即并发写 入日志的实际性能低于单线程串行写入,因此可以只启用单个消费者线程。而当日志任务 读取失败时,读接口进一步适于等待预定时间后,重新从循环队列读取日志任务。
[0046] 为验证本装置100的效果,对百万行日志的生成进行测试,从两个方面观察时间上 的消耗。表1示出了百万行日志生成测试中不同日志大小下的时间消耗对比。
[0048]表 1
[0049] 如表1所示,当日志大小为5 0 0 B时,接口调用时间为17 4 0 m s,实际写入时间为 14077ms,线程工作时间为13703毫秒;当日志大小为2KB时,接口调用时间为3535ms,实际写 入时间为16501ms,线程工作时间为16062ms。两者相比发现,当日志大小从500B增大到2KB 时,时间上的消耗并没有快速增长,这一现象在实际写入时间和线程工作时间上表现得更 明显。表2示出了百万行日志生成测试中异步写入和同步写入的时间消耗对比。
[0050]
[0051] 表 2
[0052] 如表2所示,当存在10个用户线程进行异步写入时,接口调用时间为2121ms,全部 写入时间为21435ms,线程工作时间为20824ms,总计44380ms,而10个用户线程进行同步写 入时的时间总计为48400ms。相比较之下发现,异步写入的时间消耗小于同步写入,说明本 发明的技术方案有助于降低时间消耗。
[0053] 根据本发明的一个实施例的数据传输方法,适于对以循环队列存储数据的数据存 储器进行写入和读取操作,其中循环队列以数组结构实现,具有头索引和尾索引,循环队列 中的每个元素对应一个序列号,序列号初始化为元素对应的数组下标,方法包括:接收一个 或多个生产者线程的写入指令,根据写入指令向循环队列写入数据,向循环队列写入数据 包括读取头索引并将其赋值给第一索引,通过判断第一索引指向的元素的序列号与第一索 引的大小,执行相应的数据写入操作;接收一个或多个消费者线程的读取指令,根据读取指 令从循环队列读取数据,从循环队列读取数据包括读取尾索引并将其赋值给第二索引,通 过判断第二索引指向的元素的序列号减1的值与第二索引的大小,执行相应的数据读取操 作;其中,头索引、尾索引、序列号、第一索引和第二索引均是原子对象。
[0054] 图3示出了根据本发明的一个实施例的数据传输方法中向循环队列写入数据的方 法300的流程图。如图3所示,在步骤S310中,读取头索引并将其赋值给第一索引。随后进入 步骤S320,判断第一索引指向的元素的序列号与第一索引的大小。如果第一索引指向的元 素的序列号等于第一索引,则执行步骤S331,将头索引增加1,将待写入数据写入第一索引 指向的元素中,并将序列号增加1;如果第一索引指向的元素的序列号大于第一索引,则执 行步骤S332,重新向循环队列写入数据,如果重写次数达到预设的最大重写次数,则判断数 据写入失败;如果第一索引指向的元素的序列号小于第一索引,则执行步骤S333,判断当前 循环队列已满,数据写入失败。
[0055] 图4示出了根据本发明的一个实施例的数据传输方法中从循环队列读取数据的方 法400的流程图。如图4所示,在步骤S410中,读取尾索引并将其赋值给第二索引。随后进入 步骤S420,判断第二索引指向的元素的序列号与第二索引的大小。如果第二索引指向的元 素的序列号减1的值等于第二索引,则执行步骤S431,将尾索引增加1,将待读取数据从第二 索引指向的元素中读取出来,并将序列号增加数组长度再减去1;如果第二索引指向的元素 的序列号减1的值大于第二索引,则执行步骤S432,重新从循环队列读取数据,如果重写次 数达到最大重读次数,则判断数据写入失败;如果第二索引指向的元素的序列号减1的值小 于第二索引,则执行步骤S433,判断当前循环队列已空,数据读取失败。
[0056] 在本发明的实施例中,传输的数据可以是日志任务。如果日志任务写入失败,则生 产者线程执行日志任务,生成日志文件。如果日志任务读取成功,则消费者线程执行日志任 务,生成日志文件。从循环队列读取数据的方法400还包括如果日志任务读取失败,则等待 预定时间后,重新从循环队列读取日志任务。
[0057] 关于数据传输方法的具体步骤以及实施例,在基于图1及图2(a)_(e)的描述中已 经详细公开,此处不再赘述。
[0058] 根据本发明的数据传输的技术方案,对循环队列存储数据的数据存储器进行写入 和读取操作,接收一个或多个生产者线程的写入指令来向循环队列写入数据,同时接收一 个或多个消费者线程的读取指令来从循环队列读取数据,生产者线程和消费者线程以一个 无锁循环队列为媒介进行数据传输,支持多线程在不加互斥锁的情况下同时进行数据写 入/读取操作,降低了因加锁及解锁带来的时间消耗,进一步提升了异步处理数据的能力。 [0059] A10.如A8所述的装置,其中:
[0060]所述消费者线程在所述日志任务读取成功时,执行日志任务,生成日志文件。
[0061 ] A11.如A8所述的装置,所述读接口进一步适于:
[0062]当所述日志任务读取失败时,等待预定时间后,重新从循环队列读取日志任务。 [0063] B13.如B12所述的方法,其中所述数据写入操作包括:
[0064]如果所述序列号等于第一索引,则头索引增加1,将待写入数据写入第一索引指向 的元素中,序列号增加1。
[0065] B14.如B12所述的方法,其中所述数据写入操作包括:
[0066]如果所述序列号大于第一索引,则重新向循环队列写入数据,如果重写次数达到 预设的最大重写次数,则判断数据写入失败。
[0067] B15.如B12所述的方法,其中所述数据写入操作包括:
[0068]如果所述序列号小于第一索引,则判断当前循环队列已满,数据写入失败。
[0069] B16.如B12所述的方法,其中所述数据读取操作包括:
[0070]如果所述序列号减1的值等于第二索引,则尾索引增加1,将待读取数据从第二索 引指向的元素中读取出来,序列号增加数组长度再减去1。
[0071] B17.如B12所述的方法,其中所述数据读取操作包括:
[0072] 如果所述序列号减1的值大于第二索引,则重新从循环队列读取数据,如果重写次 数达到最大重读次数,则判断数据写入失败。
[0073] B18.如B12所述的方法,其中所述数据读取操作包括:
[0074]如果所述序列号减1的值小于第二索引,则判断当前循环队列已空,数据读取失 败。
[0075] B19.如B12-18中任一项所述的方法,其中所述数据包括日志任务。
[0076] B20.如B19所述的方法,还包括:
[0077]如果所述日志任务写入失败,则由所述生产者线程执行日志任务,生成日志文件。 [0078] B21.如B19所述的方法,还包括:
[0079] 如果所述日志任务读取成功,则由所述消费者线程执行日志任务,生成日志文件。
[0080] B22.如B19所述的方法,其中所述数据读取操作还包括:
[0081 ]如果所述日志任务读取失败,则等待预定时间后,重新从循环队列读取日志任务。 [0082]在此处所提供的说明书中,说明了大量具体细节。然而,能够理解,本发明的实施 例可以在没有这些具体细节的情况下被实践。在一些实例中,并未详细示出公知的方法、结 构和技术,以便不模糊对本说明书的理解。
[0083]类似地,应当理解,为了精简本公开并帮助理解各个发明方面中的一个或多个,在 上面对本发明的示例性实施例的描述中,本发明的各个特征有时被一起分组到单个实施 例、图、或者对其的描述中。然而,并不应将该公开的方法解释成反映如下意图:即所要求保 护的本发明要求比在每个权利要求中所明确记载的特征更多特征。更确切地说,如下面的 权利要求书所反映的那样,发明方面在于少于前面公开的单个实施例的所有特征。因此,遵 循【具体实施方式】的权利要求书由此明确地并入该【具体实施方式】,其中每个权利要求本身都 作为本发明的单独实施例。
[0084]本领域那些技术人员应该理解,本发明可以在软件、固件、硬件或者其结合中实 现。本发明可以包括在具有计算机可用介质的物品中。该介质在其中具有例如计算机可读 程序代码装置或者逻辑(例如:指令,代码,命令等)来提供和使用本发明的能力。该制造物 品可作为计算机系统的一部分或者单独出售。
[0085]本领域那些技术人员应当理解在本文所公开的示例中的设备的模块或单元或组 件可以布置在如该实施例中所描述的设备中,或者可替换地可以定位在与该示例中的设备 不同的一个或多个设备中。前述示例中的模块可以组合为一个模块或者此外可以分成多个 子模块。
[0086]本领域那些技术人员可以理解,可以对实施例中的设备中的模块进行自适应性地 改变并且把它们设置在与该实施例不同的一个或多个设备中。可以把实施例中的模块或单 元或组件组合成一个模块或单元或组件,以及此外可以把它们分成多个子模块或子单元或 子组件。除了这样的特征和/或过程或者单元中的至少一些是相互排斥之外,可以采用任何 组合对本说明书(包括伴随的权利要求、摘要和附图)中公开的所有特征以及如此公开的任 何方法或者设备的所有过程或单元进行组合。除非另外明确陈述,本说明书(包括伴随的权 利要求、摘要和附图)中公开的每个特征可以由提供相同、等同或相似目的的替代特征来代 替。
[0087]此外,本领域的技术人员能够理解,尽管在此所述的一些实施例包括其它实施例 中所包括的某些特征而不是其它特征,但是不同实施例的特征的组合意味着处于本发明的 范围之内并且形成不同的实施例。例如,在下面的权利要求书中,所要求保护的实施例的任 意之一都可以以任意的组合方式来使用。
[0088]此外,所述实施例中的一些在此被描述成可以由计算机系统的处理器或者由执行 所述功能的其它装置实施的方法或方法元素的组合。因此,具有用于实施所述方法或方法 元素的必要指令的处理器形成用于实施该方法或方法元素的装置。此外,装置实施例的在 此所述的元素是如下装置的例子:该装置用于实施由为了实施该发明的目的的元素所执行 的功能。
[0089]如在此所使用的那样,除非另行规定,使用序数词"第一"、"第二"、"第三"等等来 描述普通对象仅仅表示涉及类似对象的不同实例,并且并不意图暗示这样被描述的对象必 须具有时间上、空间上、排序方面或者以任意其它方式的给定顺序。
[0090]尽管根据有限数量的实施例描述了本发明,但是受益于上面的描述,本技术领域 内的技术人员明白,在由此描述的本发明的范围内,可以设想其它实施例。此外,应当注意, 本说明书中使用的语言主要是为了可读性和教导的目的而选择的,而不是为了解释或者限 定本发明的主题而选择的。因此,在不偏离所附权利要求书的范围和精神的情况下,对于本 技术领域的普通技术人员来说许多修改和变更都是显而易见的。对于本发明的范围,对本 发明所做的公开是说明性的,而非限制性的,本发明的范围由所附权利要求书限定。
【主权项】
1. 一种数据传输装置,所述装置包括: 数据存储器,适于以循环队列存储数据,所述循环队列以数组结构实现,具有头索引和 尾索引,循环队列中的每个元素对应一个序列号,序列号初始化为元素对应的数组下标; 写接口,适于接收一个或多个生产者线程的写入指令,根据所述写入指令向循环队列 写入数据,所述向循环队列写入数据包括读取头索引并将其赋值给第一索引,通过判断第 一索引指向的元素的序列号与第一索引的大小,执行相应的数据写入操作; 读接口,适于接收一个或多个消费者线程的读取指令,根据所述读取指令从循环队列 读取数据,所述从循环队列读取数据包括读取尾索引并将其赋值给第二索引,通过判断第 二索引指向的序列号减1的值与第二索引的大小,执行相应的数据读取操作; 其中,所述头索引、尾索引、序列号、第一索引和第二索引均是原子对象。2. 如权利要求1所述的装置,所述写接口进一步适于: 当所述序列号等于第一索引时,头索引增加1,将待写入数据写入第一索引指向的元素 中,序列号增加1。3. 如权利要求1所述的装置,所述写接口进一步适于: 当所述序列号大于第一索引时,重新向循环队列写入数据,当重写次数达到预设的最 大重写次数时,判断数据写入失败。4. 如权利要求1所述的装置,所诉写接口进一步适于: 当所述序列号小于第一索引时,判断当前循环队列已满,数据写入失败。5. 如权利要求1所述的装置,所述读接口进一步适于: 当所述序列号减1的值等于第二索引时,尾索引增加1,将待读取数据从第二索引指向 的元素中读取出来,序列号增加数组长度再减去1。6. 如权利要求1所述的装置,所述读接口进一步适于: 当所述序列号减1的值大于第二索引时,重新从循环队列读取数据,当重写次数达到预 设的最大重读次数时,判断数据读取失败。7. 如权利要求1所述的装置,所述读接口进一步适于: 当所述序列号减1的值小于第二索引时,判断当前循环队列已空,数据读取失败。8. 如权利要求1-7中任一项所述的装置,其中所述数据包括日志任务。9. 如权利要求8所述的装置,其中: 所述生产者线程在所述日志任务写入失败时,执行日志任务,生成日志文件。10. -种数据传输方法,适于对以循环队列存储数据的数据存储器进行写入和读取操 作,其中所述循环队列以数组结构实现,具有头索引和尾索引,循环队列中的每个元素对应 一个序列号,序列号初始化为元素对应的数组下标,所述方法包括: 接收一个或多个生产者线程的写入指令,根据所述写入指令向循环队列写入数据,所 述向循环队列写入数据包括读取头索引并将其赋值给第一索引,通过判断第一索引指向的 元素的序列号与第一索引的大小,执行相应的数据写入操作; 接收一个或多个消费者线程的读取指令,根据所述读取指令从循环队列读取数据,所 述从循环队列读取数据包括读取尾索引并将其赋值给第二索引,通过判断第二索引指向的 元素的序列号减1的值与第二索引的大小,执行相应的数据读取操作; 其中,所述头索引、尾索引、序列号、第一索引和第二索引均是原子对象。
【文档编号】G06F9/54GK105868031SQ201610173906
【公开日】2016年8月17日
【申请日】2016年3月24日
【发明人】王冠惟
【申请人】车智互联(北京)科技有限公司