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