在开发Socket项目的时候,如果是开发一个自己玩玩,当然不用考虑效率、安全性等问题,可是如果是一个企业级的,你就不得不关注这几点。本系列文章将我们实验室里的Socket程序变成企业级的应用。
NIO编程肯定是一个很好的解决方案,不过这部分留在以后讨论。今天我想说说如何让你的阻塞的Scoket程序高效、安全的跑起来。
一开始,大家会编出一个
单线程的Scoket程序,然后我们发现这个程序根本不能够连接多个客户端,于是我们引入“
多线程”,使我们的程序能够同时处理多个客户端。
我相信,到现在为止如果没有深入研究过Socket编程,大家一般还是停留在“一客户一线程”的初级模式。如果是个位数的客户,当然你不会发现什么明显的性能问题。但是如果你的客户连接数量达到百位级,我靠,你的CPU就关顾着在各个线程间切换,你的内存似乎也有些吃不消了(每个线程都有自己独立的内存),更多的系统资源的消耗,更多的线程上下文转换,更复杂的线程管理(OS有一套自己的机制),将拖垮你的application。再加上多客户端尝试并发连接,及时响应客户端的连接将变得像癞蛤蟆追求天鹅一样不给力,因为线程的创建将占用服务器大量的CPU周期。
从
单线程到
多线程我们没法解决的问题,必然有新的英雄站出来解决,他就是“
线程池”。
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* ThreadPool演示
* @project : socket
* @author 贾懂凯 @ netjava
* @date 2010-12-14 下午12:24:40
* @since jdk1.6.0_10
*/
public class TCPServerPool {
public static void main(String args[]) throws IOException{
//ensure the parameter is right!
if(args.length!=2){
throw new IllegalArgumentException("Parameter(s):<port> <ThreadSize>");
}
int server_port=Integer.parseInt(args[0]);
int threadpool_size=Integer.parseInt(args[1]);
//create a server socket to accept client connection requests
final ServerSocket serSock=new ServerSocket(server_port);
final Logger logger=Logger.getLogger("thredPoolLog");
//spawn a fixed number of threds to service clients
for(int i=0;i<threadpool_size;i++){
Runnable run=new Runnable(){
public void run() {
while(true){
try {
Socket clientSock=serSock.accept();
/**
* 把它交给一个独立的handler处理
* 你可以将handler定义为一个独立的线程(注意性能)
* 或者定义为一个静态方法(注意并发的同步问题)。
*/
} catch (IOException e) {
logger.log(Level.WARNING,"Client accept failed",e);
}
}
}
};
Thread t=new Thread(run,"Thread-"+i);
t.start();
logger.info("create and start a thread named "+t.getName());
}
}
}
这里我为accept()方法加上了
线程池,我们发现,我们不必担心少量的多个客户并发连接的问题了,因为有多个线程对应的accept()在等待客户端连接进来。一旦客户成功连接进来,该线程重新返回线程池。如果并发访问的客户端超过线程池的size,那么连接请求将在网络中形成一个队列等待,这明显是不利于维护的,并且线程的大小没有适应性,因为它总是一成不变的。
并且连接进来的客户端显然不能交给单独的线程来处理,否则我们控制线程数量过多造成的性能瓶颈的初衷将无疾而终。不过,如果给连接进来的客户端创建一个线程池,就要考虑到维护问题,我们创建一个等待队列,来维护那些超过客户端线程池size的线程。这样将引起一致命的问题,如果其中有几个正在接受服务的线程阻塞等待或者由于未捕获异常死亡,在等待队列中的线程将因迟迟得不到资源而被饿死。
线程池的初步使用出现了这么多问题,问题总是伴随着被解决的可能性诞生的,就像出现了怪兽总会出现奥特曼一样,于是我们的英雄又出现了-“
Executor”,它是系统提供的,它可以帮助我们来管理线程池。
如何管理,待我吃完饭回来继续……(见下一篇)
分享到:
相关推荐
Java编写的简易socket通信,既有单线程socket通信也有多线程socket通信,使用Java原生sdk实现,可以运行。
多线程的FTP客户端 VC++6.0 mfc SOCKET 套接字 多线程 C/C++
serversocket单线程跟多线程例子,很值得学习的
//Runtime的availableProcessors()方法返回当前系统的CPU的数目 //系统的CPU越多,线程池中工作线程的数目也越多 executorService= Executors.newFixedThreadPool( Runtime.getRuntime()....
多线程Socket阻塞模式下通信的例子 BCB-Socket阻塞模式通讯测试(多线程) 作者:Sncel(地狱情人) QQ:6522203 指导:invalid(空心菜) QQ:309283 http://bcb.vicp.net 测试方法: 在单机上测试: 如果有多个客户...
所谓单个写入程序/多个阅读程序的线程同步问题,是指任意数量的线程访问共享资源时,写入程序(线程)需要修改共享资源,而阅读程序(线程)需要读取数据。在这个同步问题中,很容易得到下面二个要求: 1) 当一个...
用Delphi XE5 编写的 Socket多线程文件传输 客户端是单线程 服务器端是多线程 记录类型与文件流联合传输,通过记录类型传递信息给服务器 传输速度快 与网络拷贝相同 服务器端会通过MD5码验证接收到文件的正确性 并...
服务器客户端-socket(进程线程),包括套接字,多线程,多进程,单进程,并发,互斥锁,tcp/ip,udp等
简单解释下第二条:上下文切换就是cpu在多线程之间进行轮流执行(枪战cpu资源),而redis单线程的,因此避免了繁琐的多线程上下文切换。 重点解释下多路复用: 多路-指的是多个socket连接,复用-指的是复用一个线程...
该软件是一个基于java语言的socket编程,可以实现单个服务器对应多个客户端的聊天。采用swt,功能还是比较完善的。
单线程实现同时监听多个端口(windows平台c++代码)。文章查看https://www.cnblogs.com/yuanchenhui/p/icop_accept.html
实现基于服务器转发的任意多点间的数据共享与交换,仅供交流,水平有限,有不足之处还请各位大牛指点!。
简单大循环 单线程实现通信 1. TCP连接通信 2. Server先监听,等待Client连接 3. 双方都可以发"Stop!"停止通信,但此程序Client只会停止,Server可以一直监听,即断开后,Client可以再次连接 4. 不能一对多通信,...
socket通信的客户端和服务器端的工程文件,这个是多线程版本的,实现了多个客户端向服务器端持续发送数据
Java,socket多线程编程,及socket输入输出单独提出思想。
Java,socket多线程编程,及socket输入输出单独提出思想。
C++ socket 网络单、多线程源代码。这是我特定写下来分享给大家的,包含了多线程和单线程的源代码框架。是非常好的学习框架,希望对大家有帮助。 如是编译有错,加QQ497680864
Java实现简单的聊天室,单服务进程,多客户线程,用socket进行通信。适合新手学习socket。
C++语言编写,SOCKET套接字通信,分服务器和客户端,多线程模型,Win32控制台。 首先聊天室分为服务端和客户端,通过TCP连接通信。运行顺序为: 1.首先打开服务服; 2.打开客户端,用户输入名字,连接到服务端后...
IO多路复用服务器编程