利用 CountDownLatch 类实现线程同步
2014-07-19 11:54
274 查看
一、前言
我写文章总习惯开头写个前言,主要是用来介绍我遇到的问题,而所对应的文章,就是我解决这个问题的方法。本文题目所说的代码同步是相对于代码异步的。做过联网或者其他耗时应用的开发者应该知道,执行耗时操作往往都是异步处理的, 不然会阻塞主线程。但是利用异步处理也带来了一个问题,因为代码执行是按照顺序的,如果你开个子线程执行耗时操作,原来代码中,它开完子线程就会继续下面的操作,不会等待子线程结果的,这样有时候就是下面的代码要用到子线程返回的值,这时候就为空(因为子线程值还没有返回),举个例子
//伪代码 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; } }
运行后在打印台可以看到以下结果,很清楚,主线程中先打印结果,结果为空,显然不是我们所要的
三、解决方式
现在对代码做如下修改,增加代码已注释,在业务处理中加入CountDownLatchpublic 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; } }
现在再次运行,可以发现打印的结果是在线程完成之后才打印的,结果也跟我们要的是一样的。这样就实现了代码的同步。
点击这里下载源码
相关文章推荐
- Android 并发二三事之利用CountDownLatch 或 ConditionVariable实现自定义Future
- 利用关键代码段实现线程同步
- 利用事件对象实现线程同步
- 利用互斥量实现线程同步
- 利用Object的wait、notify来实现线程同步原理
- Java线程知识__其他几种线程同步的工具类的使用(CyclicBarrier,CountDownLatch,Exchanger)
- 利用互斥对象实现线程同步
- 利用互斥对象实现线程同步
- 通过Thread.join()和CountDownLatch来实现进程同步
- 利用Object的wait、notify来实现线程同步原理,Thread t1 = new Thread(new Runnable() {
- 利用互斥对象实现线程同步
- 利用关键代码段(临界区)实现线程同步
- 采用Thread.join()或CountDownLatch来实现线程间同步
- 多线程编程Demo[利用事件对象实现线程同步]
- 黑马程序员-Condition条件对象、Semaphore、CyclicBarrier、倒计时门栓 CountDownLatch、Exchanger(实现两个线程之间数据交换
- 利用互斥对象实现线程同步
- CreateMutex利用互斥对象实现线程同步实例
- 利用互斥对象实现线程同步
- 利用关键代码段实现线程同步
- java中CountDownLatch线程同步的入门使用