关于android Socket通信中线程阻塞的问题解决(有点乱,随感,有兴趣的可以看看)
2012-09-11 18:56
555 查看
前言:关于android的机制想必大家都了解, 为了避免运行一个时间长的function导致主进程阻塞,android上目前有两个方案供我们选择,一个是Thread .另一个则是Service.
UI主线程运行在Activity里,如需根据子线程的新产生数据改变UI相关的内容,需要在Handler处理,一个线程是独立于主线程的,原理上除非进程被杀死,或者用户自己停止线程,该线程在进程运行过程中一直存在。
如果不需要与用户交互,甚至不需要和进程有交互,则开启一个服务,这样即使进程关闭后台便可以帮我们轻松的处理类似下载,播放的功能。
问题:这次遇到的问题是有关于线程的,
我在这个线程中主要写了和服务器的通信功能,系统运行,和服务器建立连接,然后服务器与客户端进行数据的通信,线程一直接收,判断是否有用户请求,如果有,就发送,没有,循环。
(之前缺乏通信方面的经验,每次发请求,都建立一个连接,获取数据后关闭连接,项目小的时候没发现多大问题,项目大的时候,发现这样效率极低,回想了下网络的知识,这样很不科学额,于是改写了通信功能部分)
我发现我在线程中写的循环只进行了几次就无效了,我原本以为是Activity跳转造成的,但是仔细看了SDK之后发现无关,我很诧异,在测试文件里另外写了一个线程,证明和Activity跳转。大家都知道,由于是线程的错误,调试啥的又 看不出所以然来。我花了不少时间,检查服务器啥的。
最后逐一注释了功能模块(发现注释了红色部分线程不出现阻塞),
问题找出来了解决办法就简单了,我在这个与服务器进行通信的线程的onCreate函数开启一个接收数据流的线程,然后在它本身复写的run函数中单纯地发送请求,这样保证了一个数据发送不会因为没有收到数据包而阻塞,
改写后如下:
UI主线程运行在Activity里,如需根据子线程的新产生数据改变UI相关的内容,需要在Handler处理,一个线程是独立于主线程的,原理上除非进程被杀死,或者用户自己停止线程,该线程在进程运行过程中一直存在。
如果不需要与用户交互,甚至不需要和进程有交互,则开启一个服务,这样即使进程关闭后台便可以帮我们轻松的处理类似下载,播放的功能。
问题:这次遇到的问题是有关于线程的,
我在这个线程中主要写了和服务器的通信功能,系统运行,和服务器建立连接,然后服务器与客户端进行数据的通信,线程一直接收,判断是否有用户请求,如果有,就发送,没有,循环。
(之前缺乏通信方面的经验,每次发请求,都建立一个连接,获取数据后关闭连接,项目小的时候没发现多大问题,项目大的时候,发现这样效率极低,回想了下网络的知识,这样很不科学额,于是改写了通信功能部分)
我发现我在线程中写的循环只进行了几次就无效了,我原本以为是Activity跳转造成的,但是仔细看了SDK之后发现无关,我很诧异,在测试文件里另外写了一个线程,证明和Activity跳转。大家都知道,由于是线程的错误,调试啥的又 看不出所以然来。我花了不少时间,检查服务器啥的。
最后逐一注释了功能模块(发现注释了红色部分线程不出现阻塞),
@Override public void run() { // TODO Auto-generated method stub super.run(); while (true) { Connect(); count++; Log.v(TAG, "run" + count); if (Command.size() > 0) { try { wtr = new PrintWriter(new OutputStreamWriter( sk.getOutputStream(), "GBK")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } String send = Command.get(0); Log.v(TAG, "run/command" + send); if (send != null && send.length() > 0) { wtr.println(send); wtr.flush(); // 发送请求 }
// try { // reader = new BufferedReader(new InputStreamReader( // sk.getInputStream(), "gbk")); // if (reader != null) { // String str = reader.readLine(); // if (str.trim().length() > 0) // SortReply.sort(str); // } // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } Command.remove(0); } try { sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }原因分析,一旦服务器端没有数据发送数据给客户端,客户端就会阻塞在那里一直等待,导致线程无法继续循环。
问题找出来了解决办法就简单了,我在这个与服务器进行通信的线程的onCreate函数开启一个接收数据流的线程,然后在它本身复写的run函数中单纯地发送请求,这样保证了一个数据发送不会因为没有收到数据包而阻塞,
改写后如下:
public Client() { Log.v(TAG, "cLINET"); new getInputStreamThread().start(); } public static void set_Req(Requests request) { Command.add(request.Command); } private static void Connect() { if (sk == null) { try { sk = new Socket(ipStr, port); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (!sk.isConnected()) { try { sk.connect(new InetSocketAddress(ipStr, port)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); Log.v(TAG, "error:can not connect socket "); } } } @Override public void run() { // TODO Auto-generated method stub super.run(); while (true) { Connect(); count++; Log.v(TAG, "run" + count); if (Command.size() > 0) { try { wtr = new PrintWriter(new OutputStreamWriter( sk.getOutputStream(), "GBK")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } String send = Command.get(0); Log.v(TAG, "run/command" + send); if (send != null && send.length() > 0) { wtr.println(send); wtr.flush(); // 发送请求 } Command.remove(0); } try { sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public class getInputStreamThread extends Thread { public int aa = 0; @Override public void run() { // TODO Auto-generated method stub super.run(); while (true) { Connect(); aa++; Log.v("getInputStreamThread", "aa" + aa); try { reader = new BufferedReader(new InputStreamReader( sk.getInputStream(), "gbk")); if (reader != null) { String str = reader.readLine(); if (str.trim().length() > 0) SortReply.sort(str); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
相关文章推荐
- Android关于Socket通信异常的问题
- 关于android 使用Scoket通信中文乱码问题的解决
- 关于安卓手机做客户端pc做服务器进行Socket通信出现问题的解决案方
- Android socket通信,读去中文汉字乱码问题解决。
- 关于socket用winform实现简单通信 大牛可绕道 初学者可以看看 我做的时候把客户端窗口隐藏了 大家可以自己改一下
- 关于webrtc里面的opengl设置坐标系的问题,解决ios和android通信图像是反的问题
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)(解决不可连的问题,解决方案在最后面)
- android socket通信问题 求解决!!!!!!
- 关于webrtc里面的opengl设置坐标系的问题,解决ios和android通信图像是反的问题
- android socket通信问题 求解决!!!!!!
- 关于linux下的udp/tcp通信设置发送sendto/接收recvfrom信息超时的参数。解决通道堵塞问题。
- 关于基于jetty在android上开发未能解决的问题
- 关于android 下activity间通信的问题-广播机制
- 关于Android加载HTML页面中的图片显示问题的解决办法
- Android与PC客户端进行Socket通信的一些问题
- android中socket通信问题
- 关于Android app首次安装完成后在安装界面直接“打开”应用再按home键返回桌面,重新进入app重复实例化launcher activity的问题的解决
- 关于Android中Listview的item点击不响应问题的解决
- android 关于软键盘的显示和隐藏监听,解决挡住Editview的问题
- 回答一位朋友的问题:关于Socket通信的概述