nio学习记录一之传统io

一直在写业务代码,无非也就是增删改查,相对自己有个提升,就开始学习nio,并且打算记录下来

nio与传统的io有很大的区别,比如说非阻塞,但是具体体现在那里,本篇会介绍(如果有不足的地方请提出)

下面是一个使用传统io的socket的例子代码

public class OIoSocket {

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(20020);
        System.out.println("server start=======================");
        while (true){
            final Socket socket = serverSocket.accept();
            System.out.println("accept client==================");
            clientMsg(socket);
        }
    }
    public static void clientMsg(Socket socket){
        try{
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();

            while (true){
                int read = inputStream.read(bytes);
                if (read != -1){
                    System.out.println(new String(bytes,0,read));
                }else {
                    break;
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                System.out.println("socket close==============");
                socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}
代码很简单,我们来运行一下,并且打上断点


一步一步运行,可以看到,第一条打印是输出了,执行到accept的时候,就阻塞,下面的那个打印不会被执行

我们使用telnet来模拟个客户端


执行后发现,第二条输出执行了


这个时候,我们继续断点执行,发现在inputStream.read(bytes);这段代码时,断点停掉了,

所以可以做个总结,传统的socket有两个阻塞地方一个是server.accept();,另外一个是inputStream.read(bytes);,如果是inputStream.read(bytes);很容易就会看出,如果当前的没有执行完,又有一个新的socket进来,将在此阻塞,如下图,我又新创建了telnet,但是控制台没有任何反应,输出还是之前的



那么这就很尴尬了,如何避免呢,对代码进行如下的改造

public class OIoSocket {

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();

        ServerSocket serverSocket = new ServerSocket(20020);
        System.out.println("server start=======================");
        while (true){
            final Socket socket = serverSocket.accept();
            System.out.println("accept client==================");
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    clientMsg(socket);
                }
            });

        }
    }
    public static void clientMsg(Socket socket){
        try{
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();

            while (true){
                int read = inputStream.read(bytes);
                if (read != -1){
                    System.out.println(new String(bytes,0,read));
                }else {
                    break;
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                System.out.println("socket close==============");
                socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}


加入线程池,就会解决这个问题,做telnet不会出现上面的两个尴尬  


但是如果用这种方式,会非常消耗性能,举个例子,线程池就像是餐厅,来一个客人,就得给他准备个服务员,我擦得要多少个服务员, 老板肯定赔钱  那么怎么办?  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值