Java Socket通信技术一直活跃在编程世界中,有不少的程序员都在使用这个技术,下面我们就来看看在Java Socket通信技术中收发线程互斥的代码。

Java Socket通信技术在很长的时间里都在使用,在不少的程序员眼中都有很多高的评价。那么下面我们就看看如何才能掌握这门复杂的编程语言,希望大家在今后的Java Socket通信技术使用中有所收获。

下面就是Java Socket通信技术在解决收发线程互斥的代码介绍。

1. package com.bill99.svr;   
2. import java.io.IOException;   
3. import java.io.InputStream;   
4. import java.io.OutputStream;   
5. import java.net.InetSocketAddress;   
6. import java.net.Socket;   
7. import java.net.SocketException;   
8. import java.net.SocketTimeoutException;   
9. import java.text.SimpleDateFormat;   
10. import java.util.Date;   
11. import java.util.Properties;   
12. import java.util.Timer;   
13. import java.util.TimerTask;   
14. import java.util.concurrent.ConcurrentHashMap;   
15. import java.util.concurrent.TimeUnit;   
16. import java.util.concurrent.locks.Condition;   
17. import java.util.concurrent.locks.ReentrantLock;   
18. import org.apache.log4j.Logger;   
19. /**   
20. *<p>title: socket通信包装类</p>   
21. *<p>Description: </p>   
22. *<p>CopyRight: CopyRight (c) 2009</p>   
23. *<p>Company: 99bill.com</p>   
24. *<p>Create date: 2009-10-14</P>   
25. *author sunnylocus<A href="mailto:sunnylocus@163.com">   
26. </A> * v0.10 2009-10-14 初类   
27. * v0.11 2009-11-12 对命令收发逻辑及收发线程互斥机制进行了优化,
处理命令速度由原来8~16个/秒提高到25~32个/秒   28. */ public class SocketConnection {   
29. private volatile Socket socket;   
30. private int timeout = 1000*10; //超时时间,初始值10秒   
31. private boolean isLaunchHeartcheck = false;//是否已启动心跳检测   
32. private boolean isNetworkConnect = false; //网络是否已连接   
33. private static String host = "";   
34. private static int port;   
35. static InputStream inStream = null;   
36. static OutputStream outStream = null;   
37. private static Logger log =Logger.getLogger
(SocketConnection.class);   38. private static SocketConnection socketConnection = null;   
39. private static java.util.Timer heartTimer=null;     
40. //private final Map<String, Object> recMsgMap= Collections.
synchronizedMap(new HashMap<String, Object>());   41. private final ConcurrentHashMap<String, Object> recMsgMap 
= new ConcurrentHashMap<String, Object>();   42. private static Thread receiveThread = null;   
43. private final ReentrantLock lock = new ReentrantLock();   
44. private SocketConnection(){   
45. Properties conf = new Properties();   
46. try {   
47. conf.load(SocketConnection.class.getResourceAsStream
("test.conf"));   48. this.timeout = Integer.valueOf(conf.getProperty("timeout"));   
49. init(conf.getProperty("ip"),Integer.valueOf
(conf.getProperty("port")));   50. } catch(IOException e) {   
51. log.fatal("socket初始化异常!",e);   
52. throw new RuntimeException("socket初始化异常,请检查配置参数");   
53. }   
54. }   
55. /**   
56. * 单态模式   
57. */   
58. public static SocketConnection getInstance() {   
59. if(socketConnection==null) {   
60. synchronized(SocketConnection.class) {   
61. if(socketConnection==null) {   
62. socketConnection = new SocketConnection();   
63. return socketConnection;   
64. }   
65. }   
66. }   
67. return socketConnection;   
68. }   
69. private void init(String host,int port) throws IOException {   
70. InetSocketAddress addr = new InetSocketAddress(host,port);   
71. socket = new Socket();   
72. synchronized (this) {   
73. log.info("【准备与"+addr+"建立连接】");   
74. socket.connect(addr, timeout);   
75. log.info("【与"+addr+"连接已建立】");   
76. inStream = socket.getInputStream();   
77. outStream = socket.getOutputStream();   
78. socket.setTcpNoDelay(true);//数据不作缓冲,立即发送   
79. socket.setSoLinger(true, 0);//socket关闭时,立即释放资源   
80. socket.setKeepAlive(true);   
81. socket.setTrafficClass(0x04|0x10);//高可靠性和最小延迟传输   
82. isNetworkConnect=true;   
83. receiveThread = new Thread(new ReceiveWorker());   
84. receiveThread.start();   
85. SocketConnection.host=host;   
86. SocketConnection.port=port;   
87. if(!isLaunchHeartcheck)   
88. launchHeartcheck();   
89. }   
90. }   
91. /**   
92. * 心跳包检测   
93. */   
94. private void launchHeartcheck() {   
95. if(socket == null)   
96. throw new IllegalStateException("socket is not 
established!");   97. heartTimer = new Timer();   
98. isLaunchHeartcheck = true;   
99. heartTimer.schedule(new TimerTask() {   
100. public void run() {   
101. String msgStreamNo = StreamNoGenerator.getStreamNo("kq");   
102. int mstType =9999;//999-心跳包请求   
103. SimpleDateFormat dateformate = new SimpleDateFormat
("yyyyMMddHHmmss");   104. String msgDateTime = dateformate.format(new Date());   
105. int msgLength =38;//消息头长度   
106. String commandstr = "00" +msgLength + mstType + msgStreamNo;   
107. log.info("心跳检测包 -> IVR "+commandstr);   
108. int reconnCounter = 1;   
109. while(true) {   
110. String responseMsg =null;   
111. try {   
112. responseMsg = readReqMsg(commandstr);   
113. } catch (IOException e) {   
114. log.error("IO流异常",e);   
115. reconnCounter ++;   
116. }   
117. if(responseMsg!=null) {   
118. log.info("心跳响应包 <- IVR "+responseMsg);   
119. reconnCounter = 1;   
120. break;   
121. } else {   
122. reconnCounter ++;   
123. }   
124. if(reconnCounter >3) {//重连次数已达三次,判定网络连接中断,
重新建立连接。连接未被建立时不释放锁   125. reConnectToCTCC(); break;   
126. }   
127. }   
128. }   
129. },1000 * 60*1,1000*60*2);   
130. }   
131. /**   
132. * 重连与目标IP建立重连   
133. */   
134. private void reConnectToCTCC() {   
135. new Thread(new Runnable(){   
136. public void run(){   
137. log.info("重新建立与"+host+":"+port+"的连接");   
138. //清理工作,中断计时器,中断接收线程,恢复初始变量   
139. heartTimer.cancel();   
140. isLaunchHeartcheck=false;   
141. isNetworkConnect = false;   
142. receiveThread.interrupt();   
143. try {   
144. socket.close();   
145. } catch (IOException e1) {log.error("重连时,关闭socket连
接发生IO流异常",e1);}   146. //----------------   
147. synchronized(this){   
148. for(; ;){   
149. try {   
150. Thread.currentThread();   
151. Thread.sleep(1000 * 1);   
152. init(host,port);   
153. this.notifyAll();   
154. break ;   
155. } catch (IOException e) {   
156. log.error("重新建立连接未成功",e);   
157. } catch (InterruptedException e){   
158. log.error("重连线程中断",e);   
159. }   
160. }   
161. }   
162. }   
163. }).start();   
164. }   
165. /**   
166. * 发送命令并接受响应   
167. * @param requestMsg   
168. * @return   
169. * @throws SocketTimeoutException   
170. * @throws IOException   
171. */   
172. public String readReqMsg(String requestMsg) throws IOException {   
173. if(requestMsg ==null) {   
174. return null;   
175. }   
176. if(!isNetworkConnect) {   
177. synchronized(this){   
178. try {   
179. this.wait(1000*5); //等待5秒,如果网络还没有恢复,抛出IO流异常   
180. if(!isNetworkConnect) {   
181. throw new IOException("网络连接中断!");   
182. }   
183. } catch (InterruptedException e) {   
184. log.error("发送线程中断",e);   
185. }   
186. }   
187. }   
188. String msgNo = requestMsg.substring(8, 8 + 24);//读取流水号   
189. outStream = socket.getOutputStream();   
190. outStream.write(requestMsg.getBytes());   
191. outStream.flush();   
192. Condition msglock = lock.newCondition(); //消息锁   
193. //注册等待接收消息   
194. recMsgMap.put(msgNo, msglock);   
195. try {   
196. lock.lock();   
197. msglock.await(timeout,TimeUnit.MILLISECONDS);   
198. } catch (InterruptedException e) {   
199. log.error("发送线程中断",e);   
200. } finally {   
201. lock.unlock();   
202. }   
203. Object respMsg = recMsgMap.remove(msgNo); //响应信息   
204. if(respMsg!=null &&(respMsg != msglock)) {   
205. //已经接收到消息,注销等待,成功返回消息   
206. return (String) respMsg;   
207. } else {   
208. log.error(msgNo+" 超时,未收到响应消息");   
209. throw new SocketTimeoutException(msgNo+" 超时,未收到响应消息");   
210. }   
211. }   
212. public void finalize() {   
213. if (socket != null) {   
214. try {   
215. socket.close();   
216. } catch (IOException e) {   
217. e.printStackTrace();   
218. }   
219. }   
220. }   
221. //消息接收线程   
222. private class ReceiveWorker implements Runnable {   
223. String intStr= null;   
224. public void run() {   
225. while(!Thread.interrupted()){   
226. try {   
227. byte[] headBytes = new byte[4];   
228. if(inStream.read(headBytes)==-1){   
229. log.warn("读到流未尾,对方已关闭流!");   
230. reConnectToCTCC();//读到流未尾,对方已关闭流   
231. return;   
232. }   
233. byte[] tmp =new byte[4];   
234. tmp = headBytes;   
235. String tempStr = new String(tmp).trim();   
236. if(tempStr==null || tempStr.equals("")) {   
237. log.error("received message is null");   
238. continue;   
239. }   
240. intStr = new String(tmp);   
241. int totalLength =Integer.parseInt(intStr);   
242. //----------------   
243. byte[] msgBytes = new byte[totalLength-4];   
244. inStream.read(msgBytes);   
245. String resultMsg = new String(headBytes)+ new 
String(msgBytes);   246. //抽出消息ID   
247. String msgNo = resultMsg.substring(8, 8 + 24);   
248. Condition msglock =(Condition) recMsgMap.get(msgNo);   
249. if(msglock ==null) {   
250. log.warn(msgNo+"序号可能已被注销!响应消息丢弃");   
251. recMsgMap.remove(msgNo);   
252. continue;   
253. }   
254. recMsgMap.put(msgNo, resultMsg);   
255. try{   
256. lock.lock();   
257. msglock.signalAll();   
258. }finally {   
259. lock.unlock();   
260. }   
261. }catch(SocketException e){   
262. log.error("服务端关闭socket",e);   
263. reConnectToCTCC();   
264. } catch(IOException e) {   
265. log.error("接收线程读取响应数据时发生IO流异常",e);   
266. } catch(NumberFormatException e){   
267. log.error("收到没良心包,String转int异常,异常字符:"+intStr);   
268. }   
269. }   
270. }   
271. }   
272. }

以上就是对Java Socket通信技术中收发线程互斥的详细解决方法。