在上面一节中,服务端收到客户端的连接之后,都是new一个新的线程来处理客户端发送的请求,每次new 一个线程比较耗费系统资源,如果100万个客户端,我们就要创建100万个线程,相当的

耗费系统的资源,服务器是没有办法支持这样多的客户端进行连接的

我们可以采用线程池的方式来实现:提高

package bhz.bio2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException; public class Client { final static String ADDRESS = "127.0.0.1";
final static int PORT =8765; public static void main(String[] args) {
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(ADDRESS, PORT);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true); out.println("Client request"); String response = in.readLine();
System.out.println("Client:" + response); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (Exception e3) {
e3.printStackTrace();
}
}
socket = null;
} } }
package bhz.bio2;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; public class HandlerExecutorPool { private ExecutorService executor;
public HandlerExecutorPool(int maxPoolSize, int queueSize){
this.executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
maxPoolSize,
120L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(queueSize));
} public void execute(Runnable task){
this.executor.execute(task);
} }
package bhz.bio2;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; public class Server { final static int PORT = 8765; public static void main(String[] args) {
ServerSocket server = null;
BufferedReader in = null;
PrintWriter out = null;
try {
server = new ServerSocket(PORT);
System.out.println("server start");
Socket socket = null;
HandlerExecutorPool executorPool = new HandlerExecutorPool(50, 1000);
while(true){
socket = server.accept();
executorPool.execute(new ServerHandler(socket));
} } catch (Exception e) {
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
if(server != null){
try {
server.close();
} catch (Exception e3) {
e3.printStackTrace();
}
}
server = null;
} } }
package bhz.bio2;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket; public class ServerHandler implements Runnable { private Socket socket;
public ServerHandler (Socket socket){
this.socket = socket;
} @Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
String body = null;
while(true){
body = in.readLine();
if(body == null) break;
System.out.println("Server:" + body);
out.println("Server response");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (Exception e3) {
e3.printStackTrace();
}
}
socket = null;
} } }

阻塞模式:列如客户端请求服务器的数据,服务器如果返回10个字节的数据给客户端,如果网络较差,客户端就必须一致等待着指定10个字节发送完成,就一直阻塞着

非阻塞模式nio模式:应用程序无需等待可以直接获得服务器端的数据,无效等待,线程不会阻塞

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

同步和异步:

A. 同步
所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。

按照这个定义,其实绝大多数函数都是同步调用(例如sin isdigit等)。
但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。
最常见的例子就是 SendMessage。
该函数发送一个消息给某个窗口,在对方处理完消息之前,这个函数不返回。
当对方处理完毕以后,该函数才把消息处理函数所返回的值返回给调用者。

B. 异步
异步的概念和同步相对。
当一个异步过程调用发出后,调用者不会立刻得到结果。
实际处理这个调用的部件是在调用发出后,
通过状态、通知来通知调用者,或通过回调函数处理这个调用。

以 Socket为例,
当一个客户端通过调用 Connect函数发出一个连接请求后,调用者线程不用等待结果,可立刻继续向下运行。
当连接真正建立起来以后,socket底层会发送一个消息通知该对象。

C. 三种返回结果途径 
执行部件和调用者可以通过三种途径返回结果:
a.   状态、
b.   通知、
c.   回调函数。

总结:阻塞是针对当前的线程

同步和异步:值得的函数的返回值,同步调用者会一直等待值得服务器返回值,异步是调用该函数不会立刻得到返回值,服务器通知、或者回调的方法通知调用者

getInputStream和getOutputStream都是同步并且阻塞的模型

jdk1.7版本之前nio是同步非阻塞的,在1.7以后实现了异步非阻塞的

java scoket Blocking 阻塞IO socket通信二的更多相关文章

  1. java scoket Blocking 阻塞IO socket通信一

    package bhz.bio; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; p ...

  2. java scoket Blocking 阻塞IO socket通信四

    记住NIO在jdk1.7版本之前是同步非阻塞的,以前的inputsream是同步阻塞的,上面学习完成了Buffer现在我们来学习channel channel书双向的,以前阻塞的io的inputstr ...

  3. java scoket Blocking 阻塞IO socket通信三

    在NIO同步非阻塞的场景中和原来同步阻塞最大的却别就是引入了上面的Buffer对象,现在我们来学校上面的BUffer对象 我们来看看程序的代码: package bhz.nio.test; impor ...

  4. Java与C之间的socket通信

    最近正在开发一个基于指纹的音乐检索应用,算法部分已经完成,所以尝试做一个Android App.Android与服务器通信通常采用HTTP通信方式和Socket通信方式.由于对web服务器编程了解较少 ...

  5. java多线程实现多客户端socket通信

    一.服务端 package com.czhappy.hello.socket; import java.io.IOException; import java.net.InetAddress; imp ...

  6. Delphi和JAVA用UTF-8编码进行Socket通信例子

    最近的项目(Delphi开发),需要经常和java语言开发的系统进行数据交互(Socket通信方式),数据编码约定采用UTF-8编码. 令我无语的是:JAVA系统那边反映说,Delphi发的数据他们收 ...

  7. java与c/c++进行socket通信

    比如Server端只接收一个结构Employee,定义如下: struct UserInfo {   char UserName[20];   int UserId; }; struct Employ ...

  8. java nio--采用Selector实现Socket通信

    server: /** * 选择器服务端 * Created by ascend on 2017/6/9 9:30. */ public class SelectorServer { // publi ...

  9. 使用Socket通信(二)

    这个socket有梗,主要是服务器端有梗,可能大家会碰到同样的问题,网上查了好久,这里分享一下解决办法.首先在第一个module建一个类SimpleServer,这个类就是服务端,建好之后在代码左边有 ...

随机推荐

  1. 泛微 e-cology远程代码执行漏洞

    影响版本:泛微 e-cology<=9.0 漏洞分析: 问题出现在 resin 下 lib 中的 bsh.jar 文件里,问题类 bsh.servlet.BshServlet,可 doGet 方 ...

  2. 【docker系列2】docker 的前世今生

    Docker 入门,共 3 篇,将带大家进入 Docker 的世界.首先了解 Docker 的发展历程, 然后快速掌握 Docker 的基本使用: Docker 版本及内核兼容性选择是这部分的重点内容 ...

  3. 生成随机字符串 php

    /** +---------------------------------------------------------- * 生成随机字符串 +------------------------- ...

  4. Rocket - diplomacy - 模块结构信息

    https://mp.weixin.qq.com/s/cTRxXwWNEeb4-XX_t4bRcg   讨论模块结构信息的来源及使用方式.     ​​   1. diplomacy   diplom ...

  5. Linux (七)权限控制

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1. 概述 Linux需要对登录用户读写执行文件.进入目录.查看增删目录内容等操作进行控制,不能任由用户 ...

  6. 使用turtle库绘制一个红色五角星图形‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪

    import turtle n = eval(input("请输入五角星的长度")) turtle.begin_fill() #开始填充颜色 i = 0 while i < ...

  7. Java实现 LeetCode 819 最常见的单词(暴力)

    819. 最常见的单词 给定一个段落 (paragraph) 和一个禁用单词列表 (banned).返回出现次数最多,同时不在禁用列表中的单词. 题目保证至少有一个词不在禁用列表中,而且答案唯一. 禁 ...

  8. Java实现【USACO】1.1.2 贪婪的礼物送礼者 Greedy Gift Givers

    [USACO]1.1.2 贪婪的礼物送礼者 Greedy Gift Givers 题目描述 对于一群要互送礼物的朋友,你要确定每个人送出的礼物比收到的多多少(and vice versa for th ...

  9. Java实现 蓝桥杯VIP 算法训练 连续正整数的和

    问题描述 78这个数可以表示为连续正整数的和,1+2+3-+12,18+19+20+21,25+26+27. 输入一个正整数 n(<=10000) 输出 m 行(n有m种表示法),每行是两个正整 ...

  10. Java实现 LeetCode 402 移掉K位数字

    402. 移掉K位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示 ...