阻塞模式—多线程处理并发请求

阻塞模型的问题关键**不在于是否使用多线程(包括线程池)处理并发请求,而在于accept(),read()的操作点都被阻塞了。**下面近似模拟这个问题,模拟了20个客户端(用20个线程模拟),利用Java的同步计数器CountDownLatch保证这20个线程都初始化完成后再同时向服务器发送请求。

  • 客户端代码
package testBSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;

public class SocketClientDaemon {
    public static void main(String[] args) {
        int clientNumber = 20;
        CountDownLatch countDownLatch = new CountDownLatch(clientNumber);
        for (int i = 0; i < clientNumber ; i++, countDownLatch.countDown()) {
            SocketClientRequestThread client = new SocketClientRequestThread(i,
                    countDownLatch);
            new Thread(client).start();
        }

        // TODO
        synchronized (SocketClientDaemon.class) {
            try {
                SocketClientDaemon.class.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class SocketClientRequestThread implements Runnable {
    private int clientNum;
    private CountDownLatch countDownLatch;

    public SocketClientRequestThread(int clientNum, CountDownLatch countDownLatch) {
        this.clientNum = clientNum;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        Socket socket = null;
        InputStream clientResponse = null;
        OutputStream clientRequest = null;
        try {
            socket = new Socket("localhost", 12212);
            // TODO 输入输出流是针对内存来说的
            clientResponse = socket.getInputStream();
            clientRequest = socket.getOutputStream();

            this.countDownLatch.await();
            clientRequest.write(("这是第" + this.clientNum + "个客户端的请求").getBytes());
            clientRequest.flush();

            System.out.println("第" + this.clientNum + "个客户端发送完成,等待回复消息");
            int maxLen = 1024;
            byte[] contextBytes = new byte[maxLen];
            int readLen;
            String message = "";
            while ((readLen = clientResponse.read(contextBytes, 0, maxLen)) != -1) {
                message += new String(contextBytes, 0, readLen);
            }
            System.out.println("第" + this.clientNum + "个客户端收到服务器的信息:" + message);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }

                if (clientRequest != null) {
                    clientRequest.close();
                }

                if (clientResponse != null) {
                    clientResponse.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}
  • 服务端代码
package testBSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer2 {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(12212);
        try {
            while (true) {
                Socket socket = serverSocket.accept();
                SocketServerThread socketServerThread = new SocketServerThread(socket);
                new Thread(socketServerThread).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class SocketServerThread implements Runnable {
    private Socket socket;

    public SocketServerThread (Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InputStream is = null;
        OutputStream os = null;
        try {
            is = socket.getInputStream();
            os = socket.getOutputStream();

            Integer sourcePort = socket.getPort();

            int maxLen = 1024;
            byte[] contextBytes = new byte[maxLen];
            String message = "";

//            //不能这样写,不然会阻塞在这里
//            while ((readLen = is.read(contextBytes, 0, maxLen)) != -1) {
//                message += new String(contextBytes, 0, readLen);
//            }
            int readLen = is.read(contextBytes, 0, maxLen);
            message = new String(contextBytes, 0, readLen);
            System.out.println("服务器收到端口" + sourcePort + "的信息" + message);
            os.write("服务器回复消息".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }

                if (is != null) {
                    is.close();
                }

                if (os != null) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值