关于android Socket通信中线程阻塞的问题解决(有点乱,随感,有兴趣的可以看看)

本文探讨了在Android中使用Socket通信时遇到的线程阻塞问题。原先的实现方式每次请求都建立新的连接,效率低下。经过分析,发现问题在于接收数据的循环在运行几次后失效。通过在通信线程的onCreate中创建单独的接收数据线程,并在run函数中专注于发送请求,避免了阻塞,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:关于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();
				}

			}

		}
	}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值