关于android Socket通信中线程阻塞的问题解决

信息来源:双赞工控|时间:2017-02-15 20:34|浏览量:

 

前言:关于Android的机制想必大家都了解, 为了避免运行一个时间长的function导致主进程阻塞,android上目前有两个方案供我们选择,一个是Thread .另一个则是Service.

UI主线程运行在Activity里,如需根据子线程的新产生数据改变UI相关的内容,需要在Handler处理,一个线程是独立于主线程的,原理上除非进程被杀死,或者用户自己停止线程,该线程在进程运行过程中一直存在。

如果不需要与用户交互,甚至不需要和进程有交互,则开启一个服务,这样即使进程关闭后台便可以帮我们轻松的处理类似下载,播放的功能。

问题:这次遇到的问题是有关于线程的,

我在这个线程中主要写了和服务器的通信功能,系统运行,和服务器建立连接,然后服务器与客户端进行数据的通信,线程一直接收,判断是否有用户请求,如果有,就发送,没有,循环。

之前缺乏通信方面的经验,每次发请求,都建立一个连接,获取数据后关闭连接,项目小的时候没发现多大问题,项目大的时候,发现这样效率极低,回想了下网络的知识,这样很不科学额,于是改写了通信功能部分

我发现我在线程中写的循环只进行了几次就无效了,我原本以为是Activity跳转造成的,但是仔细看了SDK之后发现无关,我很诧异,在测试文件里另外写了一个线程,证明和Activity跳转。大家都知道,由于是线程的错误,调试啥的又 看不出所以然来。我花了不少时间,检查服务器啥的。

最后逐一注释了功能模块(发现注释了红色部分线程不出现阻塞),

[java] view plain copy
 
  1. @Override  
  2. public void run() {  
  3.     // TODO Auto-generated method stub  
  4.     super.run();  
  5.     while (true) {  
  6.         Connect();  
  7.         count++;  
  8.         Log.v(TAG, "run" + count);  
  9.         if (Command.size() > 0) {  
  10.             try {  
  11.                 wtr = new PrintWriter(new OutputStreamWriter(  
  12.                         sk.getOutputStream(), "GBK"));  
  13.             } catch (UnsupportedEncodingException e) {  
  14.                 // TODO Auto-generated catch block  
  15.                 e.printStackTrace();  
  16.             } catch (IOException e) {  
  17.                 // TODO Auto-generated catch block  
  18.                 e.printStackTrace();  
  19.             }  
  20.             String send = Command.get(0);  
  21.             Log.v(TAG, "run/command" + send);  
  22.             if (send != null && send.length() > 0) {  
  23.                 wtr.println(send);  
  24.                 wtr.flush(); // 发送请求  
  25.             }  
[java] view plain copy
 
  1. <span style="white-space: pre; ">     
  2. //<span style="white-space:pre">                </span>try {  
  3. //<span style="white-space:pre">                    </span>reader = new BufferedReader(new InputStreamReader(  
  4. //<span style="white-space:pre">                            </span>sk.getInputStream(), "gbk"));  
  5. //<span style="white-space:pre">                    </span>if (reader != null) {  
  6. //<span style="white-space:pre">                        </span>String str = reader.readLine();  
  7. //<span style="white-space:pre">                        </span>if (str.trim().length() > 0)  
  8. //<span style="white-space:pre">                            </span>SortReply.sort(str);  
  9. //<span style="white-space:pre">                    </span>}  
  10. //<span style="white-space:pre">                </span>} catch (IOException e) {  
  11. //<span style="white-space:pre">                    </span>// TODO Auto-generated catch block  
  12. //<span style="white-space:pre">                    </span>e.printStackTrace();  
  13. //<span style="white-space:pre">                </span>}<span style="color: rgb(255, 0, 0); "></span></span>  
  14.                 Command.remove(0);  
  15.             }  
  16.   
  17.             try {  
  18.                 sleep(2000);  
  19.             } catch (InterruptedException e) {  
  20.                 // TODO Auto-generated catch block  
  21.                 e.printStackTrace();  
  22.             }  
  23.   
  24.         }  
  25.     }  
原因分析,一旦服务器端没有数据发送数据给客户端,客户端就会阻塞在那里一直等待,导致线程无法继续循环。

问题找出来了解决办法就简单了,我在这个与服务器进行通信的线程的onCreate函数开启一个接收数据流的线程,然后在它本身复写的run函数中单纯地发送请求,这样保证了一个数据发送不会因为没有收到数据包而阻塞,

改写后如下:

 

[java] view plain copy
 
  1. <span style="font-family:monospace;">public Client() {  
  2.         Log.v(TAG, "cLINET");  
  3.         new getInputStreamThread().start();  
  4.   
  5.     }  
  6.   
  7.     public static void set_Req(Requests request) {  
  8.         Command.add(request.Command);  
  9.     }  
  10.   
  11.     private static void Connect() {  
  12.         if (sk == null) {  
  13.   
  14.             try {  
  15.                 sk = new Socket(ipStr, port);  
  16.             } catch (UnknownHostException e) {  
  17.                 // TODO Auto-generated catch block  
  18.                 e.printStackTrace();  
  19.             } catch (IOException e) {  
  20.                 // TODO Auto-generated catch block  
  21.                 e.printStackTrace();  
  22.             }  
  23.   
  24.         } else if (!sk.isConnected()) {  
  25.             try {  
  26.                 sk.connect(new InetSocketAddress(ipStr, port));  
  27.             } catch (IOException e) {  
  28.                 // TODO Auto-generated catch block  
  29.                 e.printStackTrace();  
  30.                 Log.v(TAG, "error:can not connect socket ");  
  31.             }  
  32.         }  
  33.     }  
  34.   
  35.     @Override  
  36.     public void run() {  
  37.         // TODO Auto-generated method stub  
  38.         super.run();  
  39.         while (true) {  
  40.             Connect();  
  41.             count++;  
  42.             Log.v(TAG, "run" + count);  
  43.             if (Command.size() > 0) {  
  44.                 try {  
  45.                     wtr = new PrintWriter(new OutputStreamWriter(  
  46.                             sk.getOutputStream(), "GBK"));  
  47.                 } catch (UnsupportedEncodingException e) {  
  48.                     // TODO Auto-generated catch block  
  49.                     e.printStackTrace();  
  50.                 } catch (IOException e) {  
  51.                     // TODO Auto-generated catch block  
  52.                     e.printStackTrace();  
  53.                 }  
  54.                 String send = Command.get(0);  
  55.                 Log.v(TAG, "run/command" + send);  
  56.                 if (send != null && send.length() > 0) {  
  57.                     wtr.println(send);  
  58.                     wtr.flush(); // 发送请求  
  59.                 }  
  60.                 Command.remove(0);  
  61.             }  
  62.   
  63.             try {  
  64.                 sleep(2000);  
  65.             } catch (InterruptedException e) {  
  66.                 // TODO Auto-generated catch block  
  67.                 e.printStackTrace();  
  68.             }  
  69.   
  70.         }  
  71.     }  
  72.   
  73.     public class getInputStreamThread extends Thread {  
  74.   
  75.         public int aa = 0;  
  76.   
  77.         @Override  
  78.         public void run() {  
  79.             // TODO Auto-generated method stub  
  80.             super.run();  
  81.             while (true) {  
  82.                 Connect();  
  83.                 aa++;  
  84.                 Log.v("getInputStreamThread""aa" + aa);  
  85.                 try {  
  86.                     reader = new BufferedReader(new InputStreamReader(  
  87.                             sk.getInputStream(), "gbk"));  
  88.                     if (reader != null) {  
  89.                         String str = reader.readLine();  
  90.                         if (str.trim().length() > 0)  
  91.                             SortReply.sort(str);  
  92.                     }  
  93.                 } catch (IOException e) {  
  94.                     // TODO Auto-generated catch block  
  95.                     e.printStackTrace();  
  96.                 }  
  97.   
  98.                 try {  
  99.                     sleep(3000);  
  100.                 } catch (InterruptedException e) {  
  101.                     // TODO Auto-generated catch block  
  102.                     e.printStackTrace();  
  103.                 }  
  104.   
  105.             }  
  106.   
  107.         }  
  108.     }  
  109. </span>