mapdb是单线程和多线程的区别还是多

我开发的产品的模块中,近期增加了一个“日志索引”功能,用于快速在多个大文件中定位运行日志。

找到一个关键模块的开源软件 mapdb,这是一个好东西啊

  将map的快速与持久化(或半持久化)功能融合在一起,就是一个JAVA嵌入式的 Redis

             本系统中用于日志索引的数据即为半持久化操作,每分钟提交一次即可,中间丢一部份数据也无所谓,设计上下次会进行“断点继续”

      将自己写的代码多处优化后,还是报类似的错误!

      虽然日志索引模块的处理有多个线程完成,但也不应该在mapdb这个处理点上报这个错误,它不是号称支持100G以上数据,支持多线程嘛?我这个才几M数据而已。

     写了2个专用于验证 mapdb的小程序,模拟本系统的使用场景进行“最简化操作”。

         程序写1000条记录没问题,1万、10万都没问题,100万条记录-----故障重现了!!太好了,能最小化用例重现故障,解决起来就方便多了。

         mapdb这个模块,应该是一个稳定的库,个人还是比较相信老外开源组织的能力及责任心,即然已确定是mapdb本身的问题,而且这么大一个BUG,其它人难道就没发现并提交开源小组修正?

      1、下载开源软件时,避免下载未发布的Beta版本,尤其是大版本有不同的开源包,大版本不同往往开发者对数据结构做了较大的调整,但还在不断完善过程中。

      2、出现故障时,在简单的排查找不到故障原因时,必须使用“最简测试用例法”,将无关的处理逻辑能去除的都去除,只留下故障模块相关的部分或重新用例,用于验证故障,此时故障更容易发现并解决

     3、作为架构师,在排查此类故障时,必须要有足够的耐心,有时查一天两天也是正常的,架构师就应该在不断思考和调整,寻找可靠性、成本、扩展性、安全性、性能等综合比较好的方案,来优化和升级现有系统,进而不断的迭代,不断反思曾经犯过的错误,这样一步步成长起来的。

    同样的批量写入,2.0能达到30万记录/秒,1.0约为7万记录/秒,正如开发者blog中所说,有4倍性能提升。

    等到2.0版本正式发布,我的系统中还是会切到2.0版本。

Java多线程环境中,为保证所有线程的执行能按照一定的规则执行,JVM实现了一个线程调度器,它定义了线程调度的策略,对于CPU运算的分配都进行了规定,按照这些特定的机制为多个线程分配CPU的使用权。这小节关注线程如何进行调度,了解了java线程调度模式有助于后面并发框架的深入探讨。

一般线程调度模式分为两种——抢占式调度和协同式调度。抢占式调度指的是每条线程执行的时间、线程的切换都由系统控制,系统控制指的是在系统某种运行机制下,可能每条线程都分同样的执行时间片,也可能是某些线程执行的时间片较长,甚至某些线程得不到执行的时间片。在这种机制下,一个线程的堵塞不会导致整个进程堵塞。协同式调度指某一线程执行完后主动通知系统切换到另一线程上执行,这种模式就像接力赛一样,一个人跑完自己的路程就把接力棒交接给下一个人,下个人继续往下跑。线程的执行时间由线程本身控制,线程切换可以预知,不存在多线程同步问题,但它有一个致命弱点:如果一个线程编写有问题,运行到一半就一直堵塞,那么可能导致整个系统崩溃。

为更加形象说明两种模式的不同,看图2-5-6-1,左边为抢占式线程调度,假如三条线程需要运行,处理器运行的路径是在线程一运行一个时间片后强制切换到线程二运行一个时间片,然后切到线程三,再回到线程一,如此循环直至三条线程都执行完。而协同式线程调度则不这样走,它会先将线程一执行完,线程一再通知线程二执行,线程二再通知线程三,直到线程三执行完。

在了解了两种线程调度模式后,现在考虑Java使用的是哪种线程调度模式。此问题的讨论涉及到JVM的实现,JVM规范中规定每个线程都有优先级,且优先级越高越优先执行,但优先级高并不代表能独自占用执行时间片,可能是优先级高得到越多的执行时间片,反之,优先级低的分到的执行时间少但不会分配不到执行时间。JVM的规范没有严格地给调度策略定义,我想正是因为面对众多不同调度策略,JVM要封装所有细节提供一个统一的策略不太现实,于是给了一个不严谨但足够统一的定义。回到问题上,Java使用的线程调度是抢占式调度,在JVM中体现为让可运行池中优先级高的线程拥有CPU使用权,如果可运行池中线程优先级一样则随机选择线程,但要注意的是实际上一个绝对时间点只有一个线程在运行(这里是相对于一个CPU来说,如果你的机器是多核的还是可能多个线程同时运行的),直到此线程进入非可运行状态或另一个具有更高优先级的线程进入可运行线程池,才会使之让出CPU的使用权,更高优先级的线程抢占了优先级低的线程的CPU

Java中线程会按优先级分配CPU时间片运行,那么线程什么时候放弃CPU的使用权?可以归类成三种情况:

  1. 当前运行线程主动放弃CPUJVM暂时放弃CPU操作(基于时间片轮转调度的JVM操作系统不会让线程永久放弃CPU,或者说放弃本次时间片的执行权),例如调用yield()方法。

  2. 当前运行线程因为某些原因进入阻塞状态,例如阻塞在I/O上。

  3. 当前运行线程结束,即运行完run()方法里面的任务。

三种情况中第三种很好理解,任务执行完了自然放弃CPU,前两种情况用两个例子说明,先看使用yield放弃CPU什么情况:

我要回帖

更多关于 单线程 的文章

 

随机推荐