参考来源:《java并发编程实战》
同步工具类:根据工具类的自身状态来协调线程的控制流。通过同步工具类,来协调线程之间的行为。
可见性:在多线程环境下,当某个属性被其他线程修改后,其他线程能够立刻看到修改后的信息。典型的是用java内置关键字volatile,volatile变量可以让jvm知道这个变量是对所有线程共享的,jvm会做一定的同步工作,但不保证原子性。
这一部分内容可以看一下http://www.cnblogs.com/dolphin0520/p/3920373.html
http://www.cnblogs.com/Mainz/p/3556430.html#
发布和逸出:
发布:发布一个对象指,使对象能够在当前作用域之外的代码使用。举个栗子就是,对象A持有对象C,把C的引用传递到其他地方,或者外界访问A有非私有方法返回C。发布一个对象时要考虑是否有足够理由发布出去,否则可能会引起同步问题。
很明显,同步工具类肯定需要发布给通信双方。
逸出:当某个不应该发布的对象被发布时,叫做逸出。
线程之间通信,就需要把一个通信协议(某个对象)发布给双方,并且对双方来说都是可见的,这样来协调线程之间的行为。当然如果有特别需要,完全可以自己去写同步工具类。
闭锁
闭锁,可以使线程等待某个事件(信号)发生后才执行后续操作。闭锁有一个初始值,当初始值为0的时候闭锁终止,所有被该闭锁阻塞的线程都可以继续执行。假设有个线程A,我们想A启动之后需要等待线程B的信号才能继续执行,这时候我们可以把一个闭锁发布给A,B,A等待闭锁的结束,B来结束闭锁,这样A就能等B的命令才能继续执行。事实上,利用闭锁还可以让主线程等待所有子线程结束。有一点要注意的是,闭锁是一次性的,一旦进入终止状态(count==0),就不能被重置。
CountDownLatch简单用法介绍:
public CountDownLatch(int count); 构造函数,当count为0的时候,await方法不再阻塞。
public void countDown(); 使count减1。
public void await(); 使当前线程阻塞,直到CountDownLatch的count为0。
下面这个例子显示了利用闭锁控制子线程执行和等待所有子线程结束。
1 public class TestDownLatch { 2 int count = 5; 3 //控制子线程执行的闭锁 4 final CountDownLatch startGate = new CountDownLatch(1); 5 //让主线程等待所有子线程结束 6 final CountDownLatch endGate = new CountDownLatch(count); 7 8 //测试线程 9 class Task extends Thread{ 10 11 int i; 12 13 public Task(int i) { 14 this.i = i; 15 } 16 17 18 @Override 19 public void run() { 20 //等待闭锁的结束 21 try { 22 //等待主线程的命令 23 startGate.await(); 24 System.out.println(i); 25 //告诉主线程我已经做完了 26 endGate.countDown(); 27 } catch (InterruptedException igored) { 28 } 29 } 30 31 } 32 33 public void test(){ 34 for (int i = 0; i < count; i++) { 35 Task task = new Task(i); 36 task.start(); 37 } 38 System.out.println("所有线程已开启"); 39 try { 40 Thread.sleep(3000); 41 startGate.countDown(); 42 System.out.println("所有子线程开始输出"); 43 44 Thread.sleep(3000); 45 endGate.await(); 46 System.out.println("主线程结束"); 47 } catch (InterruptedException ignored) { 48 } 49 50 51 } 52 53 public static void main(String[] args) { 54 TestDownLatch testDownLatch = new TestDownLatch(); 55 testDownLatch.test(); 56 } 57 58 }