Java的NIO以及线程并发

发表于:2011-12-12 09:25

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:玩玩乐乐    来源:51Testing软件测试网采编

分享:

  实际上,这段说明表明了异步socket的核心,即异步socket不过是将多个socket的调度(或者还有他们的线程调度)全部交给操作系统自己去完成,异步的核心Selector,不过是将这些调度收集、分发而已。因为操作系统的socket、线程调度再咋D也比你JVM中要强,效率也高。

  而且就算jvm做的和操作系统一样好,性能一样高(当然这是不现实的),使用异步socket你至少也节约了一半的系统消耗,想想假定操作系统本身也是使用线程来维护N个socket连接,在传统的java编程中,你还必须为这些socket还多起一个java线程,那至少是2N个线程,现在只需要N+1。在高并发的情况下,你自己去想吧。

  懂了这个道理,异步socket也就好写了,也不会搞得思路混乱了。

  三、异步Socket中应当注意的事情

  1、读

  异步socket最基本的理念就是事件通知,前面也说了,有事件通知你了,你才该做你应当做的事情。在异步socket中当注册了一个OP_READ事件后,你就等着Selector通知你吧,如果没有通知你,你在家睡大觉都行。

  在这里,我们有人出现的错误就是受同步的影响,自己去主动读,而且还搞出了多线程,如果仔细考虑一下,就不会出现这个问题了。同步socket中,调用read方法读取IO中的数据时,通常情况下如果没有数据read方法会阻塞,且是同步的,所以当多个线程同时访问时,read方法是线程安全的。

  而在异步下就不同,异步是不会阻塞的,有什么就返回什么,你主动去读,只要有数据,你就可以拿走,在多线程的情况下,也许你是想让第一个线程读取,but此时来数据时正好是线程2读到了,那线程2就高高兴兴的拿去,而线程1还在苦苦等待,这样导致数据混乱不说,如果后面再也不来数据了,线程1就是死循环啦。

  2、写

  在异步socket中,写是唯一一个主动点的操作,但是也不能直接去写Channel,而是应当先把自身注册为OP_WRITABLE,这时Selector就会发现你的存在,并把给发一个write事件,你这时后就可以写了,不过这时候有个小小的技巧,就是你执行写操作之前,请取消掉你的写注册,否则你的cpu肯定是100%。

  3、等待

  在传统的服务器编程中,由于对于每个请求都是产生的一个线程,因此你在你每个请求线程中wait也好,sleep也好,不会影响别人。但是异步不同,他的主线程只有一个,基本上每个处理都是线性的,也就是说处理完第一个,然后才能处理第二个,因此nio是一个极好的处理短连接的架构。

  我们现在出现的问题是,有人受同步的影响,没有搞清异步是如何处理,竟然在方法处理中用上sleep,而且一等还是3秒,这意味着什么,3秒才能处理一个请求,My god,我要一个3秒才能处理一个请求的服务器干嘛啊,还是60年代啊

  如果出现这样的需要等待的情况,应当另起一个线程(推荐使用线程池)去完成这个“长”时间的任务,或者将其它交给一个消息队列,通过发消息的方式将给别人去完成也行,客户端能等,你服务器怎么也能等呢?写出这样的代码,基本上一个服务器也就废了。

22/2<12
重磅发布,2022软件测试行业现状调查报告~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号