一。读写锁

  传统的同步锁就是独占式锁,当线程使用资源时候保持独占,无论读写。当人们发现请求队列(假设)中相邻请求为读-读的时候,阻塞是一种浪费资源的操作。比如公告板,所有路过的人(请求)都是读操作,并没有因为你和他在读的时候对内容造成了改变,所以在模型中,读与读操作不需要阻塞。而读写相邻则需要进行独占式操作了,因为写未完成的时候,信息是不完整的,此时读出来的信息有可能是错误的,所以写必然要保持独占式操作。而在应用程序中,读的频率是写的好几倍,也就是说如果读-读是不阻塞的,那么对性能来说是毋庸置疑的提升。

  Java中存在一种锁,名曰:ReentrantReadWriteLock。他可以实现内存中对资源操作的读写锁,读与读是不阻塞的。

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;/*** Created by MacBook on 2018/3/10.*/
public class ReadWriteLockDemo {private static Lock relock = new ReentrantLock();private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();private static Lock readLock = readWriteLock.readLock();private static Lock writeLock = readWriteLock.writeLock();private int value;public Object handleRead(Lock lock) throws Exception{try{lock.lock();Thread.sleep(1000);return value;}finally {lock.unlock();}}public void handleWrite(Lock lock,int index) throws Exception{try{lock.lock();Thread.sleep(1000);value = index;}finally {lock.unlock();}}public static void main(String[] args){ReadWriteLockDemo demo = new ReadWriteLockDemo();Runnable readThread = new Runnable() {@Overridepublic void run() {try{System.out.println("read:"+demo.handleRead(readLock));}catch (Exception e){e.printStackTrace();}}};Runnable writeThread = new Runnable() {@Overridepublic void run() {try{
//                    demo.handleWrite(relock,new Random().nextInt());demo.handleWrite(writeLock,new Random().nextInt());System.out.println("id:"+Thread.currentThread().getId()+" done!");}catch (Exception e){e.printStackTrace();}}};for(int i=0;i<18;i++){new Thread(readThread).start();}for(int i=0;i<18;i++){new Thread(writeThread).start();}}}

    此demo使用了重入锁和读写锁的对比,在主程序中分别新建18个读写操作,如果使用了读操作,则打印的读操作是连续的;如果使用了重入锁,则可能的情况是读写相邻打印,并且都是阻塞的,读者可以自行测试体会。

二。对象监视器Condition

  在JDK实现了Lock来简化synchronized之后,Condition作为简化监视器而存在。Condition的await方法和signal方法对应对象的wait和signal。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;/*** Created by MacBook on 2018/3/10.*/
public class ConditionAndLock implements Runnable{static ReentrantLock lock = new ReentrantLock();static Condition condition = lock.newCondition();public void run(){try{lock.lock();condition.await();System.out.println("thread is running");}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}}public static void main(String[] args){ConditionAndLock c = new ConditionAndLock();Thread t = new Thread(c);t.start();lock.lock();System.out.println("signal all");condition.signalAll();lock.unlock();}
}

三。倒计时器CountDownLatch

  多线程中,需要知道这批线程的最大完成任务时间,也就是从第一个任务开始到最后返回这段时间的时长,那么倒计时器是必不可少的。就像各项资源准备完毕才进行下一步操作的模型一样,CountDownLatch就是这样的多线程模型。等到所有任务调用了计数器,并且计数器总数到达某个数量时候,它才会将阻塞代码放开,让主线程往下走。

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 倒计时器* Created by MacBook on 2018/3/10.*/
public class CountDownLatchDemo implements Runnable{static CountDownLatch end = new CountDownLatch(10);static CountDownLatchDemo demo = new CountDownLatchDemo();public void run(){try{Thread.sleep(new Random().nextInt(10)*1000);System.out.println(Thread.currentThread().getId()+" check complete!");end.countDown();}catch (Exception e){e.printStackTrace();}}public static void main(String[] args) throws Exception{ExecutorService service = Executors.newFixedThreadPool(10);for(int i=0;i<10;i++){service.submit(demo);}end.await();System.out.println("fire");service.shutdown();}
}

    await方法是阻塞倒计时器所在线程的方法,等到线程池service中调用countDown方法到达一定的数量(此处是10)之后,主线程的await方法才会过去。

四。信号量

  信号量这个东西就比较玄乎了,有点像准入许可,拿到信号准入的时候才往下执行。就像是有一批人拿号,只有号码区间在某个范围的人能进去办事,然后办完事就会让资源释放,号码区间往后移。然而在信号量中应该算是复用类型的,归还了key值,将key值返回给下一个申请者。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;/*** Created by MacBook on 2018/3/10.*/
public class SemapDemo implements Runnable{final Semaphore semp = new Semaphore(5);public void run(){try{semp.acquire();Thread.sleep(2000);System.out.println(Thread.currentThread().getId()+" done!");semp.release();}catch (Exception e){e.printStackTrace();}}public static void main(String[] args){ExecutorService executorService = Executors.newFixedThreadPool(5);SemapDemo semapDemo = new SemapDemo();for(int i=0;i<20;i++){executorService.submit(semapDemo);}executorService.shutdown();}
}

  在acquire获得key之后,操作读写,之后release。

五。栅栏

  栅栏和倒计时器很像,就是拦住一堆线程,等到线程数达到某个设定值之后同时把它们放出去。但是不同的是,它可以每次设定值达成时候运行定制线程中的run方法。就像是每次一个栏,够数就放。

import java.util.Random;
import java.util.concurrent.CyclicBarrier;/*** Created by MacBook on 2018/3/10.*/
public class CylicBarrierDemo {public static class Soldier implements Runnable{private String soldier;private final CyclicBarrier cyclicBarrier;Soldier(String soldier,CyclicBarrier cyclicBarrier){this.soldier = soldier;this.cyclicBarrier = cyclicBarrier;}public void run(){try{cyclicBarrier.await();doWork();cyclicBarrier.await();}catch (Exception e){e.printStackTrace();}}public void doWork(){try{Thread.sleep(Math.abs(new Random().nextInt()%10000));}catch (Exception e){e.printStackTrace();}System.out.println(soldier + " done!");}}public static class BarrierRun implements Runnable{boolean flag;int n;public BarrierRun(boolean flag,int n){this.flag = flag;this.n = n;}public void run(){if(flag){System.out.println("士兵:"+n+"个 done!");}else {System.out.println("士兵:"+n+"个 集合完毕!");flag = true;}}}public static void main(String[] args){final int n = 10;Thread[] allSoldier = new Thread[n];boolean flag = false;CyclicBarrier cyclic = new CyclicBarrier(n,new BarrierRun(flag,n));System.out.println("集合");for(int i =0; i < n ; i++){System.out.println("士兵 "+i+" 报道");allSoldier[i] = new Thread(new Soldier("士兵"+i,cyclic));allSoldier[i].start();}}
}

  例中CyclicBarrier有两个参数,前一个就是提到的设定值,后一个就是定制线程了。每当到达设定值的时候会触发定制线程。

  每个阶段完成都会调用一下定制线程。

六。LockSupport提供线程挂起操作的支持类

  正如Condition使得原有的Object监视器封装成了新类,LockSupport提供使线程park和unpark之类的操作。

import java.util.concurrent.locks.LockSupport;/*** Created by MacBook on 2018/3/10.*/
public class LockSupportDemo {public static Object u = new Object();static ChangeObjectThread t1 = new ChangeObjectThread("t1");static ChangeObjectThread t2 = new ChangeObjectThread("t2");public static class ChangeObjectThread extends Thread{public ChangeObjectThread(String name){super.setName(name);}public void run(){synchronized (u){System.out.println("in "+getName());LockSupport.park();}}}public static void main(String[] args) throws Exception{t1.start();Thread.sleep(100);t2.start();LockSupport.unpark(t1);LockSupport.unpark(t2);t1.join();t2.join();}}

  它在park时候线程会变成wait状态,而不是runnable。

  来自《Java高并发程序设计》的读书笔记

转载于:https://www.cnblogs.com/chentingk/p/8540823.html

Concurrent包工具类使用相关推荐

  1. 高并发编程基础(java.util.concurrent包常见类基础)

    JDK5中添加了新的java.util.concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法 ...

  2. Java封装OkHttp3工具类

    点击关注公众号,Java干货及时送达  作者:如漩涡 https://blog.csdn.net/m0_37701381 Java封装OkHttp3工具类,适用于Java后端开发者 说实在话,用过挺多 ...

  3. Java 并发之Concurrent 包综述

    ■ 并发原理 单核系统:线程交替执行,由于交替又快又多,给人一种同时执行的感觉 多核系统:不仅可以交替执行线程,而且可以重叠执行线程 补充: 本章指的并发主要指的是线程间的并发 ■ 常见的并发机制 ■ ...

  4. 项目常用工具类整理(五)--jar包整理

    2019独角兽企业重金招聘Python工程师标准>>> SSH框架: Struts1.2.9+Spring2.5+Hibernate3.2 说明:commons的几个包算是公用Jar ...

  5. 【JDK源码】java.util.concurrent.atomic包常用类详解

    java.util.concurrent.atomic原子操作类包里面提供了一组原子变量类.其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方 ...

  6. 多线程十 JUC包下的常用工具类

    JUC包下的常用工具类 1. CountDownLatch-闭锁 2. CyclicBarrier-循环栅栏 3. Semaphore-信号量 4. Exchanger-线程数据交换器 这篇文章主要是 ...

  7. Apache Commons包 StringUtils工具类深入整理(转载)

    [转载地址]:cnblogs.com/sealy321/p/10227131.html 字符串是在程序开发中最常见的,Apache Commons开源项目在org.apache.commons.lan ...

  8. java 克隆对象工具类_关于dorado-core源码包中CloneUtils克隆工具类对对象进行克隆复制操作...

    一.前言 基于dorado.core.jar开源包中的com.bstek.dorado.util.CloneUtils克隆工具类,对对象进行通过java.lang.reflect.Method映射克隆 ...

  9. java 集合反射_关于granite源码包CollectionUtil集合工具类获取集合反射类型、实例化各种集合类型HashSet/ArrayList等...

    一.前言 基于granite源码包org.granite.util.CollectionUtil集合工具类,分别获取集合反射类型java.lang.reflect.Type.实例化newCollect ...

最新文章

  1. mysql 第一天_MySQL第一天
  2. Laravel 5 中间件、路由群组、子域名路由、 权限控制的基本使用方法
  3. python出现中文乱码 RuntimeWarning: Glyph 24180 missing from current font.解决方法
  4. 业务异常 java_java – 具有业务异常的Hystrix断路器
  5. 模拟(堆):USACO Jan11 瓶颈
  6. 3D优化之ShadowGun系列三:shader系列汇总
  7. Centos6.10系统迁移到新固态硬盘LVM
  8. [EKL-踩坑记] —— ES虚拟内存设置
  9. 交易心得(简要总结)
  10. 打印机墨水添加方法(二)
  11. 夜神模拟器的安装和使用
  12. 新版火狐 拖 功能_Firefox 33的新功能
  13. Spring Boot 学习笔记 9 : EasyPoi
  14. 全球及中国计算机仿真产业发展热点及运营能力状况分析报告2021-2027年版
  15. NodeMCU 通过MQTT 连接阿里云物联网
  16. cherry键盘G80-3000s无法使用组合快捷键
  17. GO冷门又重要的知识点(一)
  18. 鉴于现有的形式化方法(简称“桥”系列)有其优点和缺点,特发明新的“秤”系列
  19. UltraEdit添加到右键管理
  20. 【netcore】 ASP.NET Core 中间件

热门文章

  1. 8运行不了_好消息!十堰新建28座充电站,年底投入运行
  2. eslint检测node 内部模块报错解决方案
  3. 微信小程序点击按钮实现手机振动功能
  4. 最优化:**回归/拟合方法总结
  5. CSS3实现侧边栏快速定位的隐藏和消失
  6. 记一次mogodb占用cpu高问题
  7. Sicily 1346. 金明的预算方案
  8. Entity Framework 4 in Action读书笔记——第三章:查询对象模型基础(1)
  9. 使用LOAD DATA和INSERT语句导入Mysql数据
  10. SQL Server 2005的30项顶尖特性