日期:2014-05-20  浏览次数:21180 次

OutputStream的write和flush方法会堵塞当前线程么?
比如我要向远端传1G的数据,需要10分钟,那线程是一直堵塞在那里还是异步执行当前线程继续走下一步?

------解决方案--------------------
感觉楼上2位都答非所问

按照楼主的假设,你用OutputStream的write传1G的数据,需要10分钟,那么当前线程就会在这个地方停留10分钟,直到write返回。
------解决方案--------------------
探讨
我是用接收到的Socket创建了一个返回OutputStream流,现在遇到一个很难重现的情况,之前对方客户端会发生错误说我这里强制关闭了一个连接(不是经常有但是会发生),我这里没有报错,看了半天会不会是因为我用OutputStream返回内容时再还没有完全写光就Close掉了连接,因为在write和flush之后紧跟的就是Close(包括关闭Socket和OutputStream)

------解决方案--------------------
Java code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 这个程序仅仅是为了让你明白服务端或者客户端关闭对双方造成的影响(其实没啥影响..)
 * 发生你的异常的原因主要是你尝试向一个服务/客户端已经关闭的输入流输出内容
 * 通过调整一些属性可以更改这个程序的运行流程 用Lock来保证程序的执行顺序(通过设置IS_CLOSE_SERVER来确定是先关闭服务端还是客户端 另外凡是先关闭那一方都是负责输出内容)
 * @author Lv9
 */
public class StudySocket {
    static final int PORT = 14455;
    static final boolean IS_CLOSE_SERVER = true;// true为先关闭服务端 false为先关闭客户端
    static final Lock LOCK = new ReentrantLock();

    static java.util.concurrent.atomic.AtomicBoolean isAccpet = new AtomicBoolean();

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

    static void send(OutputStream o, String message) {
        PrintWriter out = new PrintWriter(o);
        out.print("Hello World");
        out.flush();
        out.close();
        System.err.println("OutputStream is closed");
    }

    static String receive(InputStream i) throws IOException {
        StringBuilder result = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(i));

        String line = null;
        while ((line = reader.readLine()) != null) {
            result.append(line).append("\r\n");
        }

        reader.close();
        
        System.err.println("InputStream is closed");
        return result.toString();
    }

    static class Client implements Runnable {
        private Socket client;

        public Client() {
        }

        @Override
        public void run() {
            try {
                try {
                    while (!isAccpet.get()) {
                        TimeUnit.SECONDS.sleep(2);
                    }
                    if (!IS_CLOSE_SERVER) {
                        LOCK.lock();
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                this.client = new Socket(InetAddress.getLocalHost(), PORT);

                if (!IS_CLOSE_SERVER) {
                    send(client.getOutputStream(), "I'm client.");
                    LOCK.unlock();
                } else {
                    LOCK.lock();
                    System.err.println(receive(client.getInputStream()));
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    static class Server implements Runnable {
        private ServerSocket server;

        public Server() {
            try {
                this.server = new ServerSocket(PORT);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void run() {
            Socket socket = null;
            try {
                if (IS_CLOSE_SERVER) {
                    LOCK.lock();
                }
                isAccpet.set(true);
                socket = server.accept();

                if (IS_CLOSE_SERVER) {
                    send(socket.getOutputStream(), "I'm server.");

                    LOCK.unlock();
                } else {
                    LOCK.lock();
                    System.err.println(receive(socket.getInputStream()));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}