Java同步工具类总结
2016-05-12 11:15
666 查看
本文可作为传智播客《张孝祥-Java多线程与并发库高级应用》的学习笔记。
synchronized保证了,我管理的那部分代码同一时刻只有一个线程能访问
Semaphore保证了,我管理的那部分代码同一时刻最多可以有n个线程访问
例如下面的例子,5个人去旅游,设置abc三个中途节点,所有人都到达a之后在继续走向b,所有人都到达b,然后才继续走向c。
看下面这个图
这就是CycleBarrier,线程自己管理自己,大家看到人都到齐了,才继续走。
这个是CountDownLatch,由他人来协调进度。
例如跑步的时候,有个裁判,等所有的人都到齐了,他吹哨,然后大家开始跑,等所有人都跑完了,他才公布成绩。
CountDownLatch里面有个计数器,初始值就是new countdownlatch时传入的
wait方法会一直等待,直到计数器的值变为0
coutdown方法可以让计数器的值减一
B线程有数据2,它需要与A线程的数据1做交换
那么什么时候交换呢?得等AB都做好准备才行。
////////////////////////////////////////////////////////////////
以下为2016-9-1日更新
这里补充一些JUC包下常见类的实现
线程池 内部有worker,worker就是一个个车,runnable就是一个个人,每个worker会包装人
参考资料http://blog.csdn.net/wojiaolinaaa/article/details/51345789
CycleBarrier
调用了ReentrantLock的lock
Semaphore于CountDownLatch 使用了AbstractQueuedSynchronizer
阻塞队列使用的也是ReentrantLock的lock
ArrayBlockingQueue内部是一个数组,但是可以循环,怎么循环呢?takeindex与putindex是两个索引,到数组的长度后,就再变成0
future是用locksupport的park函数
以上为2016-9-1日更新
///////////////////////////////////////////////////////////////
Semaphore
这个东西和之前的synchronized干的事差不多。synchronized保证了,我管理的那部分代码同一时刻只有一个线程能访问
Semaphore保证了,我管理的那部分代码同一时刻最多可以有n个线程访问
package cn.itcast.heima2; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SemaphoreTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Semaphore sp = new Semaphore(3); for(int i=0;i<10;i++){ Runnable runnable = new Runnable(){ public void run(){ try { sp.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("线程" + Thread.currentThread().getName() + "进入,当前已有" + (3-sp.availablePermits()) + "个并发"); try { Thread.sleep((long)(Math.random()*10000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程" + Thread.currentThread().getName() + "即将离开"); sp.release(); //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元 System.out.println("线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3-sp.availablePermits()) + "个并发"); } }; service.execute(runnable); } } }
CycleBarrier
CycleBarrier 能做到让n个线程互相等待,当n个线程都做到某一步后,再继续下一步。例如下面的例子,5个人去旅游,设置abc三个中途节点,所有人都到达a之后在继续走向b,所有人都到达b,然后才继续走向c。
package cn.itcast.heima2; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CyclicBarrierTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(3); for(int i=0;i<3;i++){ Runnable runnable = new Runnable(){ public void run(){ try { Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); cb.await(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); } service.shutdown(); } }
CountDownLatch
它保证了什么功能呢?其实和CycliBarrier也类似。看下面这个图
这就是CycleBarrier,线程自己管理自己,大家看到人都到齐了,才继续走。
这个是CountDownLatch,由他人来协调进度。
例如跑步的时候,有个裁判,等所有的人都到齐了,他吹哨,然后大家开始跑,等所有人都跑完了,他才公布成绩。
package cn.itcast.heima2; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountdownLatchTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch cdOrder = new CountDownLatch(1); final CountDownLatch cdAnswer = new CountDownLatch(3); for(int i=0;i<3;i++){ Runnable runnable = new Runnable(){ public void run(){ try { System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令"); cdOrder.await(); System.out.println("线程" + Thread.currentThread().getName() + "已接受命令"); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结果"); cdAnswer.countDown(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); } try { Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将发布命令"); cdOrder.countDown(); System.out.println("线程" + Thread.currentThread().getName() + "已发送命令,正在等待结果"); cdAnswer.await(); System.out.println("线程" + Thread.currentThread().getName() + "已收到所有响应结果"); } catch (Exception e) { e.printStackTrace(); } service.shutdown(); } }
CountDownLatch里面有个计数器,初始值就是new countdownlatch时传入的
wait方法会一直等待,直到计数器的值变为0
coutdown方法可以让计数器的值减一
Exchange
A线程有数据1,它需要与B线程的数据2做交换B线程有数据2,它需要与A线程的数据1做交换
那么什么时候交换呢?得等AB都做好准备才行。
package cn.itcast.heima2; import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExchangerTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Exchanger<String> exchanger = new Exchanger<String>(); service.execute(new Runnable(){ public void run() { try { String data1 = "zxx"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 +"换出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); }catch(Exception e){ } } }); service.execute(new Runnable(){ public void run() { try { String data1 = "lhm"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 +"换出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); }catch(Exception e){ } } }); } }
////////////////////////////////////////////////////////////////
以下为2016-9-1日更新
这里补充一些JUC包下常见类的实现
线程池 内部有worker,worker就是一个个车,runnable就是一个个人,每个worker会包装人
参考资料http://blog.csdn.net/wojiaolinaaa/article/details/51345789
CycleBarrier
调用了ReentrantLock的lock
Semaphore于CountDownLatch 使用了AbstractQueuedSynchronizer
阻塞队列使用的也是ReentrantLock的lock
ArrayBlockingQueue内部是一个数组,但是可以循环,怎么循环呢?takeindex与putindex是两个索引,到数组的长度后,就再变成0
future是用locksupport的park函数
以上为2016-9-1日更新
///////////////////////////////////////////////////////////////
相关文章推荐
- C#通过Semaphore类控制线程队列的方法
- rsync相对于其他同步工具的优缺点介绍
- C#使用semaphore来管理异步下载请求的方法
- Python多线程同步Lock、RLock、Semaphore、Event实例
- JAVA 多线程之信号量(Semaphore)实例详解
- Java多线程编程之CountDownLatch同步工具使用实例
- Python多进程同步Lock、Semaphore、Event实例
- Windows Server 2008 R2上部署Exchange Server 2010图文教程
- Java并发同步工具类之CountDownLatch
- SMTPClient连接EXCHANGE2007发送邮件
- 在 Exchange 资源林拓扑中部署 Exchange 2010
- Exchange邮件服务器中的部署更改
- Exchange公用文件夹恢复及常见问题
- Exchange 分析器工具介绍及案例分析
- Exchange动态同步中的INTERNET_29错误代码
- Exchange Server 2003的虚拟服务器中使用证书
- Exchange 2003 使用队列查看器的秘籍
- Exchange Server退信(NDR)及解决方案总汇
- Exchange 2013 CU11安装错误