美文网首页
InputStream的阻塞和非阻塞

InputStream的阻塞和非阻塞

作者: 刘琛_2e0c | 来源:发表于2020-04-12 01:34 被阅读0次

一、背景

    写了一个使用 InputStream 接收 Socket 字节流的 demo ,发现只要 socket 不关闭的情况下读这个InputStream 会一直 block。如果是读的是 FileInputStream,读完文件却会立刻返回。

二、原理分析

    行为的差异主要来自 InputStream 。Socket 的 InputStream 在 tcp 链接断开后(收到 tcp Fin 请求)会给 InputStream 一个信号代表所有数据已经读完了,连接已经断开不可能再拿到任何数据了。这时通过 InputStream 进行读取会直接返回 -1 或 null,不会继续 block 了。如果没有收到 Fin 请求,读取 InputStream 会一直 block 。这点上和 FileInputStream 就不同了,FileInputStream 如果读到了文件结尾得到 EOF 就会返回,即便后续再有数据写入文件也拿不到了,只能重新读一次。

三、代码验证

    同时读写文件:两个线程分别读写一个文件,虽然写线程一直在写,但是读线程很快就返回了,不会等读线程写完。

package com.zhuo.io;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedInputStreamTest {

    private static final String fileName = "/Users/lc/mine/b.txt";

    public static class WriteThread implements Runnable {
        public void run() {
            try {
                FileOutputStream fileOutputStream = new FileOutputStream(fileName);
                int i = 0;
                while (i++ < 10) {
                    fileOutputStream.write(("hello" + i).getBytes());
                    Thread.sleep(1);
                }
                fileOutputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("write thread ends...");
        }
    }

    public static class ReadThread implements Runnable {
        public void run() {
            try {
                BufferedInputStream bufferedInputStream =
                        new BufferedInputStream(new FileInputStream(fileName));
                int c;
                while ((c = bufferedInputStream.read()) != -1) {
                    System.out.print((char) c);
                }
                System.out.println();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("read thread ends...");
        }
    }

    public static void main(String[] args) throws Exception {
        new Thread(new WriteThread()).start();
        new Thread(new ReadThread()).start();
    }
}

    读socket:在socket不关闭的情况下,即便client不发送数据,server侧socket的inputStream读取始终是block的。

package com.lc;

import static com.lc.Constants.PORT;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketClient {

    public static class SocketThread implements Runnable {
 
        public SocketThread(Inet4Address address, int port) {
            try {
                this.socket = new Socket(address, port);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }

        private Socket socket;

        public void run() {
            try {
                int i = 0;
                while (i++ < 100) {
                    socket.getOutputStream().write(("hello" + i + "\n").getBytes());
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                throw new IllegalStateException();
            }
        }
    }

    public static void main(String[] args) {
        byte[] ip = {127, 0, 0, 1};
        try {
            SocketThread socketThread = new SocketThread((Inet4Address) InetAddress.getByAddress("local", ip), 34456);
            new Thread(socketThread).start();
        } catch (UnknownHostException unknownHostException) {
            throw new RuntimeException(unknownHostException);
        }
    }
}

package com.lc;

import static com.lc.Constants.PORT;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer {

    public static class SocketThread implements Runnable {

        public SocketThread(int port) {
            try {
                this.serverSocket = new ServerSocket(port);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }

        private ServerSocket serverSocket;

        public void run() {
            try {
                Socket socket = serverSocket.accept();
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
                String line = null;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (Exception e) {
                throw new IllegalStateException();
            }
        }

        public static void main(String[] args) {
            new Thread(new SocketThread(34456)).start();
        }
    }


}

相关文章

  • InputStream的阻塞和非阻塞

    一、背景 写了一个使用 InputStream 接收 Socket 字节流的 demo ,发现只要 socket ...

  • Ok I/O 简析

    java 的NIO和阻塞I/O 阻塞I/O通信模式:调用InputStream.read()方法时是阻塞的,它会一...

  • 非阻塞和阻塞

    ### 同步 任务的执行顺序和程序的执行顺序一致,所以是同步的。 ### 异步 每一个任务都有一个或多个回调函数,...

  • 阻塞和非阻塞

    含义: 阻塞:干不完不许回来 非阻塞:你先干,干完告诉我一声。 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回...

  • 有关java多线程的文章

    先行概念 阻塞队列和非阻塞队列 阻塞和非阻塞队列的区别概念:https://www.cnblogs.com/min...

  • 谈论:同步异步阻塞非阻塞.md

    同步/异步:关注的方式(是否主动) 阻塞/非阻塞: 同步阻塞BIO: 同步非阻塞NIO: 异步非阻塞: 异步阻塞:

  • BIO NIO AIO

    IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。 阻塞和非阻塞:是针对于进程在访...

  • 并发编程之并发队列

    常见的并发队列有2种:阻塞队列和非阻塞队列。阻塞队列使用锁实现,非阻塞队列使用CAS非阻塞算法实现。这2种队列都是...

  • IO多路复用 2021-10-03

    阻塞和非阻塞 进程进入waiting状态,就是阻塞阻塞/非阻塞,关注的是调用方的状态,往往是与系统调用(syste...

  • 好记性不如烂笔头——NIO学习笔记

    本文是对NIO知识的归纳与整理 1.阻塞与同步 1)阻塞(Block)和非租塞(NonBlock): 阻塞和非阻塞...

网友评论

      本文标题:InputStream的阻塞和非阻塞

      本文链接:https://www.haomeiwen.com/subject/anymmhtx.html