`

如果你用单线程写Socket,为什么要折腾?--单线程、多线程、线程池

阅读更多
在开发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”,它是系统提供的,它可以帮助我们来管理线程池。
如何管理,待我吃完饭回来继续……(见下一篇)
分享到:
评论
8 楼 zhaoxin1943 2010-12-16  
贾懂凯 写道
taolei0628 写道
用Executor不见得就比你现在的方法好。
等你贴出线程池的用法后再看看有没有我预计到的问题出现吧。
给你个提示,网络连接是个比线程更重量级的资源。

确实如此,三次握手会占比较长时间,只有到第三次握手完成才会返回socket实例。我觉得如果并发访问要求比较高的话,用我上面的代码中的线程池方法应该能增加效率。不过,如果在accept方法上加一个超时机制效果会更好。
求taolei0628指点~~

楼主为何不考虑用现成的框架呢?我们项目也需要用到socket编程,前一阵子用过netty,后来发现XSocket更好用。
7 楼 贾懂凯 2010-12-15  
taolei0628 写道
用Executor不见得就比你现在的方法好。
等你贴出线程池的用法后再看看有没有我预计到的问题出现吧。
给你个提示,网络连接是个比线程更重量级的资源。

确实如此,三次握手会占比较长时间,只有到第三次握手完成才会返回socket实例。我觉得如果并发访问要求比较高的话,用我上面的代码中的线程池方法应该能增加效率。不过,如果在accept方法上加一个超时机制效果会更好。
求taolei0628指点~~
6 楼 贾懂凯 2010-12-15  
下一篇昨天就写了大家可能没看见。链接:http://www.iteye.com/topic/842139#1804671
5 楼 taolei0628 2010-12-15  
用Executor不见得就比你现在的方法好。
等你贴出线程池的用法后再看看有没有我预计到的问题出现吧。
给你个提示,网络连接是个比线程更重量级的资源。
4 楼 joknm 2010-12-15  
我什么也没看到。。。
3 楼 贾懂凯 2010-12-15  
greedsluck 写道
嗯,不错,这样行了吧

谢谢捧场,呵呵~~
2 楼 贾懂凯 2010-12-15  
yumcn.com 写道
这个也叫线程池啊,你应该使用concurrent包的ThreadPoolExecutor

在我的下一篇文章里有写,这篇只是引入。
1 楼 yumcn.com 2010-12-15  
这个也叫线程池啊,你应该使用concurrent包的ThreadPoolExecutor

相关推荐

    单线程与多线程socket通信

    首先,我们来详细探讨单线程Socket通信。在单线程模型中,服务器端只有一个线程处理所有客户端的连接请求。当一个客户端发起连接请求时,服务器端创建一个Socket实例,并通过这个Socket实例与客户端进行通信。这种...

    JAVA 写的SOCKET线程池

    Java中的Socket线程池是一种高效的网络编程模型,它结合了Socket通信和多线程技术,以提高服务端处理客户端请求的并发性能。对于初学者来说,理解并掌握这个概念至关重要,因为这能帮助他们构建更稳定、可扩展的网络...

    linux下多线程读写socket的简单例子

    在多线程读写Socket的应用中,我们可能会创建一个主线程负责监听和接收连接,然后为每个新的客户端连接创建一个单独的线程来处理读写操作,这样可以避免单线程模型下的阻塞问题,提高服务端的并发处理能力。...

    Java Socket学习---单线程阻塞

    "Java Socket学习---单线程阻塞"这个主题主要探讨了如何使用Java的Socket类进行单线程的阻塞式通信,这种模式通常用于简单的客户端-服务器应用。在这个场景中,服务器端通过一个线程处理一个客户端的请求,当请求被...

    serversocket单线程跟多线程例子

    本文将深入探讨`ServerSocket`在单线程和多线程环境下的应用,以及它们各自的特点和适用场景。 首先,我们来看`ServerSocket`的单线程例子。在单线程模式下,服务器只有一个线程来处理所有客户端的连接请求。这通常...

    socket编程 使用select与线程池

    线程池是一种线程使用模式,它预先创建了一组线程,当有任务需要执行时,线程池会分配一个空闲线程来执行任务,任务完成后,线程返回线程池等待下一次分配。这种方式提高了系统资源的利用率,减少了线程创建和销毁的...

    C++多线程SOCKET收发

    在C++编程中,多线程SOCKET收发是一项重要的技术,它允许程序同时处理多个网络连接,提高系统的并发性能。...通过学习和实践这个主题,你可以深入理解C++的多线程特性和网络编程,提升软件的性能和用户体验。

    socket服务器线程池的实现

    2. **多线程编程**:线程是程序执行的最小单元,C++中可以通过`#include &lt;thread&gt;`库来创建和管理线程。每个连接到服务器的客户端请求都可以作为一个独立的任务在新线程中处理,这样可以避免主线程阻塞,提高并发...

    多线程与socket网络编程-内附视频链接-新手入门资料

    在IT领域,多线程和Socket网络编程是两个至关重要的概念,它们对于开发高效、可靠的分布式系统至关重要。这里我们将深入探讨这两个主题。 1. **进程** - **进程的定义**:进程是操作系统中资源分配的基本单位,它...

    Windows Socket编程 多线程

    总的来说,Windows Socket编程与多线程的结合是构建高性能网络服务的核心技术之一,对于想要深入理解和开发网络应用的IT从业者来说,这是不可或缺的知识点。通过不断地学习和实践,开发者能够更好地理解和驾驭这一...

    异步和多线程socket通讯

    本文将深入探讨"异步和多线程socket通讯"这一主题,基于提供的描述和标签,我们将讨论如何利用多线程和异步机制来提升socket通信的效率和响应性。 首先,Socket是一种在应用程序与网络服务之间建立连接的接口,它...

    delphi多线程socket编程介绍

    ### Delphi多线程Socket编程介绍 随着分布式系统的广泛应用,多任务并发技术变得越来越重要。在当前基于多线程的操作系统环境下,开发并发多任务程序已成为软件开发领域的一个热点话题。Delphi作为一种强大的开发...

    单线程Socket编程实现mysql数据读取

    - 考虑到多线程,如果服务器需要处理多个客户端连接,可以使用线程池或并发框架。 - 数据安全,对敏感信息如数据库密码进行加密处理。 - 数据的序列化和反序列化要确保两端的兼容性。 以上就是使用单线程Socket编程...

    socket短连接和长连接 多线程的应用

    学习这个框架可以帮助理解如何在实际应用中有效地管理和使用Socket连接,以及如何通过多线程和线程池优化并发性能。通过阅读和分析源码,可以深入理解这些概念,并提升网络编程和并发处理的能力。

    java Socket 多线程

    Java Socket 多线程是网络编程中的一个重要概念,它结合了Java的并发处理能力和Socket通信技术,使得服务器能够同时处理多个客户端的连接请求。在Java中,Socket是用于在网络环境中进行双向通信的类,而多线程则允许...

    C# 多线程socket客户端

    本篇文章将深入探讨如何使用C#构建一个多线程的Socket客户端,特别是针对聊天室场景。 标题中的"C# 多线程socket客户端"指的是在C#环境中,利用Socket类和多线程技术来创建一个能够并发处理多个连接的客户端应用。...

    C# 多线程socket 实例

    C#作为一种功能强大的.NET编程语言,提供了丰富的库支持来实现网络通信,其中包括使用socket进行多线程编程。本篇文章将深入探讨如何在C#中利用多线程和socket技术创建一个聊天室实例。 首先,理解`socket`的概念至...

    delphi多线程socket服务器客户端

    通过上述步骤,你可以构建一个基础的Delphi多线程Socket服务器客户端系统,实现高效、稳定的网络通信。随着需求的增加,可以扩展功能,如添加多线程池管理、数据压缩、消息队列等高级特性,以提升系统的性能和可靠性...

    c#超级Socket库SuperSocket,SOCKET多线程编程

    综上所述,SuperSocket库为C#开发者提供了一个强大而灵活的Socket服务开发框架,通过多线程处理、易于扩展的API以及跨平台支持,使得构建Socket应用变得更加高效和便捷。通过学习和掌握SuperSocket,开发者可以快速...

    socket多线程通信

    Socket多线程通信是网络编程中的一个重要概念,它结合了Socket接口与多线程技术,以提高服务端处理客户端请求的效率。C/S(Client/Server)模型是网络通信的基本架构,其中C代表客户端,S代表服务器端。在这个模型中...

Global site tag (gtag.js) - Google Analytics