Java Socket通信技术收发线程互斥的解决方法
Java Socket通信技术在很长的时间里都在使用,在不少的程序员眼中都有很多高的评价。那么下面我们就看看如何才能掌握这门复杂的编程语言,希望大家在今后的JavaSocket通信技术使用中有所收获。
下面就是Java Socket通信技术在解决收发线程互斥的代码介绍。
- packagecom.bill99.svr;
- importjava.io.IOException;
- importjava.io.InputStream;
- importjava.io.OutputStream;
- importjava.net.InetSocketAddress;
- importjava.net.Socket;
- importjava.net.SocketException;
- importjava.net.SocketTimeoutException;
- importjava.text.SimpleDateFormat;
- importjava.util.Date;
- importjava.util.Properties;
- importjava.util.Timer;
- importjava.util.TimerTask;
- importjava.util.concurrent.ConcurrentHashMap;
- importjava.util.concurrent.TimeUnit;
- importjava.util.concurrent.locks.Condition;
- importjava.util.concurrent.locks.ReentrantLock;
- importorg.apache.log4j.Logger;
- /**
- *<p>title:socket通信包装类</p>
- *<p>Description:</p>
- *<p>CopyRight:CopyRight(c)2009</p>
- *<p>Company:99bill.com</p>
- *<p>Createdate:2009-10-14</P>
- *authorsunnylocus<Ahref="mailto:sunnylocus@163.com">
- </A>*v0.102009-10-14初类
- *v0.112009-11-12对命令收发逻辑及收发线程互斥机制进行了优化,
处理命令速度由原来8~16个/秒提高到25~32个/秒 - */publicclassSocketConnection{
- privatevolatileSocketsocket;
- privateinttimeout=1000*10;//超时时间,初始值10秒
- privatebooleanisLaunchHeartcheck=false;//是否已启动心跳检测
- privatebooleanisNetworkConnect=false;//网络是否已连接
- privatestaticStringhost="";
- privatestaticintport;
- staticInputStreaminStream=null;
- staticOutputStreamoutStream=null;
- privatestaticLoggerlog=Logger.getLogger
(SocketConnection.class); - privatestaticSocketConnectionsocketConnection=null;
- privatestaticjava.util.TimerheartTimer=null;
- //privatefinalMap<String,Object>recMsgMap=Collections.
synchronizedMap(newHashMap<String,Object>()); - privatefinalConcurrentHashMap<String,Object>recMsgMap
=newConcurrentHashMap<String,Object>(); - privatestaticThreadreceiveThread=null;
- privatefinalReentrantLocklock=newReentrantLock();
- privateSocketConnection(){
- Propertiesconf=newProperties();
- try{
- conf.load(SocketConnection.class.getResourceAsStream
("test.conf")); - this.timeout=Integer.valueOf(conf.getProperty("timeout"));
- init(conf.getProperty("ip"),Integer.valueOf
(conf.getProperty("port"))); - }catch(IOExceptione){
- log.fatal("socket初始化异常!",e);
- thrownewRuntimeException("socket初始化异常,请检查配置参数");
- }
- }
- /**
- *单态模式
- */
- publicstaticSocketConnectiongetInstance(){
- if(socketConnection==null){
- synchronized(SocketConnection.class){
- if(socketConnection==null){
- socketConnection=newSocketConnection();
- returnsocketConnection;
- }
- }
- }
- returnsocketConnection;
- }
- privatevoidinit(Stringhost,intport)throwsIOException{
- InetSocketAddressaddr=newInetSocketAddress(host,port);
- socket=newSocket();
- synchronized(this){
- log.info("【准备与"+addr+"建立连接】");
- socket.connect(addr,timeout);
- log.info("【与"+addr+"连接已建立】");
- inStream=socket.getInputStream();
- outStream=socket.getOutputStream();
- socket.setTcpNoDelay(true);//数据不作缓冲,立即发送
- socket.setSoLinger(true,0);//socket关闭时,立即释放资源
- socket.setKeepAlive(true);
- socket.setTrafficClass(0x04|0x10);//高可靠性和最小延迟传输
- isNetworkConnect=true;
- receiveThread=newThread(newReceiveWorker());
- receiveThread.start();
- SocketConnection.host=host;
- SocketConnection.port=port;
- if(!isLaunchHeartcheck)
- launchHeartcheck();
- }
- }
- /**
- *心跳包检测
- */
- privatevoidlaunchHeartcheck(){
- if(socket==null)
- thrownewIllegalStateException("socketisnot
established!"); - heartTimer=newTimer();
- isLaunchHeartcheck=true;
- heartTimer.schedule(newTimerTask(){
- publicvoidrun(){
- StringmsgStreamNo=StreamNoGenerator.getStreamNo("kq");
- intmstType=9999;//999-心跳包请求
- SimpleDateFormatdateformate=newSimpleDateFormat
("yyyyMMddHHmmss"); - StringmsgDateTime=dateformate.format(newDate());
- intmsgLength=38;//消息头长度
- Stringcommandstr="00"+msgLength+mstType+msgStreamNo;
- log.info("心跳检测包->IVR"+commandstr);
- intreconnCounter=1;
- while(true){
- StringresponseMsg=null;
- try{
- responseMsg=readReqMsg(commandstr);
- }catch(IOExceptione){
- log.error("IO流异常",e);
- reconnCounter++;
- }
- if(responseMsg!=null){
- log.info("心跳响应包<-IVR"+responseMsg);
- reconnCounter=1;
- break;
- }else{
- reconnCounter++;
- }
- if(reconnCounter>3){//重连次数已达三次,判定网络连接中断,
重新建立连接。连接未被建立时不释放锁 - reConnectToCTCC();break;
- }
- }
- }
- },1000*60*1,1000*60*2);
- }
- /**
- *重连与目标IP建立重连
- */
- privatevoidreConnectToCTCC(){
- newThread(newRunnable(){
- publicvoidrun(){
- log.info("重新建立与"+host+":"+port+"的连接");
- //清理工作,中断计时器,中断接收线程,恢复初始变量
- heartTimer.cancel();
- isLaunchHeartcheck=false;
- isNetworkConnect=false;
- receiveThread.interrupt();
- try{
- socket.close();
- }catch(IOExceptione1){log.error("重连时,关闭socket连
接发生IO流异常",e1);} - //----------------
- synchronized(this){
- for(;;){
- try{
- Thread.currentThread();
- Thread.sleep(1000*1);
- init(host,port);
- this.notifyAll();
- break;
- }catch(IOExceptione){
- log.error("重新建立连接未成功",e);
- }catch(InterruptedExceptione){
- log.error("重连线程中断",e);
- }
- }
- }
- }
- }).start();
- }
- /**
- *发送命令并接受响应
- *@paramrequestMsg
- *@return
- *@throwsSocketTimeoutException
- *@throwsIOException
- */
- publicStringreadReqMsg(StringrequestMsg)throwsIOException{
- if(requestMsg==null){
- returnnull;
- }
- if(!isNetworkConnect){
- synchronized(this){
- try{
- this.wait(1000*5);//等待5秒,如果网络还没有恢复,抛出IO流异常
- if(!isNetworkConnect){
- thrownewIOException("网络连接中断!");
- }
- }catch(InterruptedExceptione){
- log.error("发送线程中断",e);
- }
- }
- }
- StringmsgNo=requestMsg.substring(8,8+24);//读取流水号
- outStream=socket.getOutputStream();
- outStream.write(requestMsg.getBytes());
- outStream.flush();
- Conditionmsglock=lock.newCondition();//消息锁
- //注册等待接收消息
- recMsgMap.put(msgNo,msglock);
- try{
- lock.lock();
- msglock.await(timeout,TimeUnit.MILLISECONDS);
- }catch(InterruptedExceptione){
- log.error("发送线程中断",e);
- }finally{
- lock.unlock();
- }
- ObjectrespMsg=recMsgMap.remove(msgNo);//响应信息
- if(respMsg!=null&&(respMsg!=msglock)){
- //已经接收到消息,注销等待,成功返回消息
- return(String)respMsg;
- }else{
- log.error(msgNo+"超时,未收到响应消息");
- thrownewSocketTimeoutException(msgNo+"超时,未收到响应消息");
- }
- }
- publicvoidfinalize(){
- if(socket!=null){
- try{
- socket.close();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- }
- //消息接收线程
- privateclassReceiveWorkerimplementsRunnable{
- StringintStr=null;
- publicvoidrun(){
- while(!Thread.interrupted()){
- try{
- byte[]headBytes=newbyte[4];
- if(inStream.read(headBytes)==-1){
- log.warn("读到流未尾,对方已关闭流!");
- reConnectToCTCC();//读到流未尾,对方已关闭流
- return;
- }
- byte[]tmp=newbyte[4];
- tmp=headBytes;
- StringtempStr=newString(tmp).trim();
- if(tempStr==null||tempStr.equals("")){
- log.error("receivedmessageisnull");
- continue;
- }
- intStr=newString(tmp);
- inttotalLength=Integer.parseInt(intStr);
- //----------------
- byte[]msgBytes=newbyte[totalLength-4];
- inStream.read(msgBytes);
- StringresultMsg=newString(headBytes)+new
String(msgBytes); - //抽出消息ID
- StringmsgNo=resultMsg.substring(8,8+24);
- Conditionmsglock=(Condition)recMsgMap.get(msgNo);
- if(msglock==null){
- log.warn(msgNo+"序号可能已被注销!响应消息丢弃");
- recMsgMap.remove(msgNo);
- continue;
- }
- recMsgMap.put(msgNo,resultMsg);
- try{
- lock.lock();
- msglock.signalAll();
- }finally{
- lock.unlock();
- }
- }catch(SocketExceptione){
- log.error("服务端关闭socket",e);
- reConnectToCTCC();
- }catch(IOExceptione){
- log.error("接收线程读取响应数据时发生IO流异常",e);
- }catch(NumberFormatExceptione){
- log.error("收到没良心包,String转int异常,异常字符:"+intStr);
- }
- }
- }
- }
- }
以上就是对Java Socket通信技术中收发线程互斥的详细解决方法。希望大家有所领悟。