OutputStream的write和flush方法会堵塞当前线程么?

wsxqaz 2011-12-20 05:14:10
比如我要向远端传1G的数据,需要10分钟,那线程是一直堵塞在那里还是异步执行当前线程继续走下一步?
...全文
885 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
BearKin 2011-12-21
  • 打赏
  • 举报
回复
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();
}
}
}
}
BearKin 2011-12-21
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wsxqaz 的回复:]
流程是我先接收对方发给我的一个Socket包,然后处理完毕,使用这个Socket创建的OutputStream返回结果,然后我直接关闭这个Socket,我这里是不是应该不需要关闭Socket让对方去关闭?
[/Quote]
我给你写个例子比对下效果吧.. 然后你自己判断你应该如何去做
wsxqaz 2011-12-20
  • 打赏
  • 举报
回复
流程是我先接收对方发给我的一个Socket包,然后处理完毕,使用这个Socket创建的OutputStream返回结果,然后我直接关闭这个Socket,我这里是不是应该不需要关闭Socket让对方去关闭?
Java大失叔 2011-12-20
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wsxqaz 的回复:]
我是用接收到的Socket创建了一个返回OutputStream流,现在遇到一个很难重现的情况,之前对方客户端会发生错误说我这里强制关闭了一个连接(不是经常有但是会发生),我这里没有报错,看了半天会不会是因为我用OutputStream返回内容时再还没有完全写光就Close掉了连接,因为在write和flush之后紧跟的就是Close(包括关闭Socket和OutputStream)
[/Quote]

你在OutputStream的write和flush后,马上Close的话,对方就90%都会从他那边的输入流中读不到东西,而是会从输入流中读到-1。
按照楼主的描述,你写的应该是服务端,你在回复完数据后,不能关闭socket。而是要等待对方来关闭,或者到了你设定的一个超时时长。
BearKin 2011-12-20
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wsxqaz 的回复:]
我是用接收到的Socket创建了一个返回OutputStream流,现在遇到一个很难重现的情况,之前对方客户端会发生错误说我这里强制关闭了一个连接(不是经常有但是会发生),我这里没有报错,看了半天会不会是因为我用OutputStream返回内容时再还没有完全写光就Close掉了连接,因为在write和flush之后紧跟的就是Close(包括关闭Socket和OutputStream)
[/Quote]

如果你关闭了连接 那么客户端会出错 但是你这头不会有什么影响(毕竟你都关闭连接了) 所以客户端尝试向你发送数据的时候出现异常

我并不清楚你的业务 一般是双方做个协定 比如客户端发送了某个命令后服务端得知客户端将关闭连接 于是自己关闭连接 你这头是咋回事呢?
Java大失叔 2011-12-20
  • 打赏
  • 举报
回复
感觉楼上2位都答非所问

按照楼主的假设,你用OutputStream的write传1G的数据,需要10分钟,那么当前线程就会在这个地方停留10分钟,直到write返回。
wsxqaz 2011-12-20
  • 打赏
  • 举报
回复
我是用接收到的Socket创建了一个返回OutputStream流,现在遇到一个很难重现的情况,之前对方客户端会发生错误说我这里强制关闭了一个连接(不是经常有但是会发生),我这里没有报错,看了半天会不会是因为我用OutputStream返回内容时再还没有完全写光就Close掉了连接,因为在write和flush之后紧跟的就是Close(包括关闭Socket和OutputStream)
warriorLv 2011-12-20
  • 打赏
  • 举报
回复
线程的作用就是解决你的这种问题,它会独立执行它的代码。不会影响其它的
BearKin 2011-12-20
  • 打赏
  • 举报
回复
如果你用阻塞IO的话 就会阻塞(比如Socket) 如果你用非阻塞IO就不会阻塞(SocketChannel 开启非阻塞模式用ByteBuffer输出数据)

另外 IO阻塞是阻塞的一种情况 正常操作系统也有IO阻塞 只是阻塞时间太短你感受不到而已

67,515

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧