利用 CountDownLatch 类实现线程同步

一、前言

我写文章总习惯开头写个前言,主要是用来介绍我遇到的问题,而所对应的文章,就是我解决这个问题的方法。

本文题目所说的代码同步是相对于代码异步的。做过联网或者其他耗时应用的开发者应该知道,执行耗时操作往往都是异步处理的, 不然会阻塞主线程。但是利用异步处理也带来了一个问题,因为代码执行是按照顺序的,如果你开个子线程执行耗时操作,原来代码中,它开完子线程就会继续下面的操作,不会等待子线程结果的,这样有时候就是下面的代码要用到子线程返回的值,这时候就为空(因为子线程值还没有返回),举个例子

//伪代码

int a = 1;
int b = 子线程返回结果;//这里开个子线程获取b的值
int c = a + b;//这时候就会出问题,因为执行这一步的时候b值还没有返回

按照上面伪代码例子,执行到 int c = a + b; 就会报错,原因是b的值为空,因为子线程还没结束。

当然也可以利用接口进行回调,然后在回调当中继续执行主线程中的代码,但是有时候这样的方法是麻烦的,回调多的时候处理起来也麻烦,我们这里也不是要讨论这个问题,毕竟很多时候一个问题的解决方法有很多种,当我们能够掌握多种之后,就能够选择最优的那种了,如果对回调方法感兴趣也可以看下我写过的另外一篇文章(android应用开发MVC框架(一)),里面就是有涉及到利用回调机制实现的。而本文就是要实现另外一种解决方式,就是使用CountDownLatch让代码实现同步,如果对CountDownLatch不是很了解务必度娘了解下。


二、demo描述问题

还是喜欢用实践的方式去描述和解决一个具体存在的问题,这样应该最有说服力。首先看看原先代码,这是没有使用CountDownLatch的。

程序入口,很简单:

public class TestActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		System.out.println("begin...");
		Business business = new Business();
		String s = business.getResult();//开启子线程
		System.out.println("结果:"+s);
	}
	
}

业务类,模拟耗时操作,这里没有使用CountDownLatch:

public class Business {

	private String result = "";
	
	public Business() {
		
	}
	
	public String getResult(){
		new Thread(){
			@Override
			public void run() {
				System.out.println("线程开始");
				try {
					Thread.sleep(5 * 1000);//测试超过5秒也不会ANR
					result = "这是数据这是数据";
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					System.out.println("线程完成");
					System.out.println("正确返回的结果应该是这样的:"+result);
				}
			}
		}.start();
		return result;
	}

}

运行后在打印台可以看到以下结果,很清楚,主线程中先打印结果,结果为空,显然不是我们所要的




三、解决方式

现在对代码做如下修改,增加代码已注释,在业务处理中加入CountDownLatch

public class Business {

	private String result = "";
	
	public Business() {
		
	}
	
	public String getResult(){
		final CountDownLatch countDownLatch = new CountDownLatch(1);//新增加的
		new Thread(){
			@Override
			public void run() {
				System.out.println("线程开始");
				try {
					Thread.sleep(15 * 1000);
					result = "这是数据这是数据";
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					System.out.println("线程完成");
					countDownLatch.countDown();//新增加的
					System.out.println("正确返回的结果应该是这样的:"+result);
				}
			}
		}.start();
		try {
			countDownLatch.await();//新增加的
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return result;
	}

}

现在再次运行,可以发现打印的结果是在线程完成之后才打印的,结果也跟我们要的是一样的。这样就实现了代码的同步。




点击这里下载源码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>