IO(BIO)同步阻塞IO
IO又称同步阻塞IO,是最古老的Tcp通信方式,需要建立在三次握手后通信,而且是点对点直连的方式通信
server端
public class Server {
final static int PROT = 8765;
public static void main(String[] args) {
ServerSocket server = null;
try {
server = new ServerSocket(PROT);
System.out.println(" server start .. ");
//进行阻塞
Socket socket = server.accept();
//新建一个线程执行客户端的任务
new Thread(new ServerHandler(socket)).start();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(server != null){
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
server = null;
}
}
client
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("接收到客户端的请求数据...");
out.println("接收到客户端的请求数据1111...");
String response = in.readLine();
System.out.println("Client: " + response);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
socket = null;
}
}
}
ServerHander
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("服务器端回送响的应数据.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
socket = null;
}
}
}
tcp直连方式存在很多缺点
- 需要三次握手后才能通信
- 网络状态不稳定,印象通信质量
- 每次有新的客户端连接都都需要创建一个线程进行通信
伪异步IO
在server创建一个线程池,用于接受客户端的连接所创建的线程,所有和 客户端通信的线程都交由线程池进行管理
server
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;
}
}
}
HandlerExecutorPool
public class HandlerExecutorPool {
private ExecutorService executor;
/**
*
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)使用给定的初始参数和默认线程工厂创建一个新的ThreadPoolExecutor ,并拒绝执行处理程序。 使用Executors工厂方法之一可能更方便,而不是这种通用构造函数。
参数
corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于核心时,这是多余的空闲线程在终止之前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位
workQueue - 在执行任务之前用于保存任务的队列。 该队列将仅保存execute方法提交的Runnable任务。
异常
IllegalArgumentException - 如果以下某项成立:
corePoolSize < 0
keepAliveTime < 0
maximumPoolSize <= 0
maximumPoolSize < corePoolSize
Nul lPointerException - 如果 workQueue为空
*
*/
public HandlerExecutorPool(int maxPoolSize, int queueSize){
this.executor = new ThreadPoolExecutor(
/**
* public int availableProcessors()返回可用于Java虚拟机的处理器数量。
在虚拟机的特定调用期间,此值可能会更改。 因此,对可用处理器数量敏感的应用程序应偶尔轮询此属性并适当调整其资源使用情况。
结果
虚拟机可用的最大处理器数量; 从不小于一个
*/
Runtime.getRuntime().availableProcessors(),
maxPoolSize,
120L,
/**
* DAYS
时间单位代表二十四小时
HOURS
时间单位代表六十分钟
MICROSECONDS
时间单位代表千分之一毫秒
MILLISECONDS
时间单位为千分之一秒
MINUTES
时间单位代表60秒
NANOSECONDS
时间单位代表千分之一千分之一
SECONDS
时间单位代表一秒
*/
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(queueSize));
}
public void execute(Runnable task){
this.executor.execute(task);
}
}