redis的队列究竟是否线程安全?
Redis作为一款流行的内存缓存数据库,其队列功能也是其最为经典的特性之一。然而,许多Redis用户都对于Redis的队列是否线程安全存在疑虑。本文将就此问题进行探讨。
我们需要了解Redis的队列模型。Redis的队列模型是基于列表(List)的,具体而言,即是左进左出的列表模型,也就是我们常说的FIFO(First-In First-Out)模型。
例如,我们可以通过Redis的LPUSH命令向队列的左端添加元素;通过Redis的LPOP命令从队列的左端弹出第一个元素;通过Redis的RPUSH命令向队列的右端添加元素;通过Redis的RPOP命令从队列的右端弹出第一个元素。而所有的这些操作都是原子操作,可以保证在多线程环境下的数据一致性。
然而,虽然Redis的队列操作是原子操作,但是在Redis客户端多线程环境下操作同一个Redis服务时,存在出现竞态条件的可能。
竞态条件是指多个线程同时对同一份数据做出并发修改,从而导致数据不一致的现象。在Redis多线程环境下,如果多个线程同时执行LPUSH或者RPUSH命令,就可能导致多个元素同时插入队列,从而导致数据被覆盖。
那么针对这种情况,我们有哪些解决方案呢?下面将介绍两种常见的解决方案:
1.加锁
加锁是保证Redis队列线程安全的常见方法。通过Redis的SETNX命令实现,其中SETNX命令可以保证只有一个客户端能够获得锁,从而保证队列操作的线性化。例如,我们可以使用以下代码实现Redis队列的线程安全操作:
class RedisQueue{private Jedis jedis = new Jedis("localhost");private static final String lockKey = "RedisQueueLock";public synchronized long enqueue(String key,String value) {long status = jedis.setnx(lockKey, "1");if (status == 1) {long result = jedis.lpush(key, value);jedis.del(lockKey);return result;}return 0;}public synchronized String dequeue(String key) {long status = jedis.setnx(lockKey, "1");if (status == 1) {String result = jedis.rpop(key);jedis.del(lockKey);return result;}return null;}}
2.使用Lua脚本
在Redis 2.6之后,Redis提供了一种使用Lua脚本来实现多个命令的原子性的方法。我们可以使用Lua脚本来保证Redis的队列操作的原子性,从而保证线程安全。例如,我们可以使用以下代码实现Redis队列的线程安全操作:

class RedisQueue{private Jedis jedis = new Jedis("localhost");private static final String LPOP_SCRIPT = "local key = KEYS[1]\n" +"local value = redis.call('lpop',key)\n" +"return value";private static final String RPOP_SCRIPT = "local key = KEYS[1]\n" +"local value = redis.call('rpop',key)\n" +"return value";public String enqueue(String key,String value) {return jedis.lpush(key, value).toString();}public String dequeue(String key) {return jedis.eval(LPOP_SCRIPT,1,key).toString();}}
综上所述,Redis的队列操作本身是线程安全的,但是在多个线程同时对同一个Redis服务执行队列操作时,需要采取相应的措施来保证线程安全。常见的方法包括加锁和使用Lua脚本。这样,在多线程环境下,我们就可以放心使用Redis的队列功能了。
香港服务器首选树叶云,2H2G首月10元开通。树叶云(www.IDC.Net)提供简单好用,价格厚道的香港/美国云 服务器 和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。
为什么网上这么多的病毒?没办法解决吗?
病毒一般解决方案(原创)首先建议使用最新的专业杀毒软件和木马专杀工具Ewido 4.0和卡巴斯基等进行处理,如遇杀毒软件被禁用或杀毒失败或一开机就重新出现的情况:(如果是IE上网浏览的问题,先阅读步骤4 !!)1.打开windows任务管理器,察看是否有可疑的进程(可以根据杀毒软件的报告或者在网上搜索相关信息来判定)在运行,如果有把它结束。 注意在system32目录下的本身不是病毒,有可能一个dll文件在运行,他才可能是病毒或恶意程序之类的东西。 由于windows任务管理器不能显示进程的路径,因此建议使用杀毒软件自带的进程察看和管理工具来查找并中止可疑进程。 然后设法找到病毒程序文件(主要是你所中止的病毒进程文件,另外先在资源管理器的文件夹选项中,设置显示所有文件和文件夹、显示受保护的文件,再察看如system32文件夹中是否有不明dll或exe文件,C:\Program Files C:\Documents and Settings\user\Local Settings\Temporary Internet Files C:\Documents and Settings\user\Local Settings\Temp 等处是否有不明文件或病毒程序文件),然后删去,搞清楚是否是系统文件再动手。 2.有些病毒进程终止不了,提示“拒绝访问”,或者出现“屡禁不止”的情况。 根据我的经验,有三种办法供尝试:A.可能是某些木马病毒、流氓软件等注册为系统服务了。 办法是:察看控制面板〉管理工具〉服务,看有没有与之相关的服务(特别是“描述”为空的)在运行,把它停止。 再试着中止病毒进程并删除。 B.你可以尝试安全模式下(开机后按F8选安全模式)用杀毒软件处理,不行则再按步骤1和2A试一试。 C.(慎用)使用冰刃等工具,察看病毒进程的线程信息和模块信息,尝试结束线程和解除模块,再试着删除病毒进程文件和相应的模块。 (慎用)3.如果稍微懂得注册表使用的,可以再把相关的注册表键值删除。 一般方法:开始〉运行,输入regedit,确定,打开注册表编辑器。 编辑〉查找,查找目标为病毒进程名,在搜索结果中将与之有关的键值删除。 有时这样做不能遏止病毒,还应尝试使用步骤2中方法。 4.某些病毒会劫持IE浏览器,导致乱弹网页的状况。 建议用金山毒霸的金山反间谍 2006等修复工具。 看浏览器辅助对象BHO是否有可疑项目。 有就修复它。 修复失败时参照1、2来做。 5.其他提示:为了更好的操作,请先用优化大师或超级兔子清理所有临时文件和上网时的缓存文件。 一般病毒往往在临时文件夹Temp中,这样做可以帮你更快找到病毒文件。 开始〉运行,输入msconfig,确定,可以打开“系统配置实用程序”。 选择“启动”,察看开机时加载的程序,如果在其中发现病毒程序,可以禁止它在开机时加载。 不过此法治标不治本,甚至对某些程序来说无效。 还是要按步骤1、2办。 6.说了这么多,不过有时还是不能解决。 只好请教高人或格式化重做系统了,当然不推荐后者!病毒一般解决方案(原创)
ArrayList,LinkedList,Set的区别是什么?
ArrayList 实现List接口 ,随着向 ArrayList 中不断添加元素,其容量也自动增长对于处理一列数据项,Java提供了两个类ArrayList和LinkedList, ArrayList的内部实现是基于内部数组Object[], 所以从概念上讲,它更象数组,但LinkedList的内部实现是基于一组连接的记录,所以,它更象一个链表结构,所以,它们在性能上有很大的差别。在ArrayList的前面或中间插入数据时,你必须将其后的所有数据相应的后移,这样必然要花费较多时间,所以,当你的操作是在一列 数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能而访问链表中的某个元素时,就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了Set一个不包含重复元素的容器
JAVA中SET 和 GET 的用法
我来回答:通常set 和 get是属性的存取器,一般称getter/setter。 set表示设置值,get表示获取值。 在Eclipse中先定义好字段后,选择Source/Generate Getters and Setters可以根据选择自动生成这些方法,JBuilder中对应有BeanInfo的功能。 get方法返回的类型必须为该字段对应的类型;set方法返回的类型一般为void,但传入的类型应为该字段对应的类型。 所以,jawdat的写法应该修改为: public String getName() {}public void setName(String name) {}
发表评论