首页 > java的concurrent包

java的concurrent包

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

最近在网上看到一个将concurrent包的系列文章,仔细读了一遍,感觉不错。

分享一下:http://www.hetaoblog.com/myblogs/post/%E8%AF%B4%E4%B8%80%E8%AF%B4java%E7%9A%84concurrent%E5%8C%851-%E6%95%B4%E4%BD%93%E4%BB%8B%E7%BB%8D.jhtml

Concurrent包主要有三个package组成。java.util.concurrent:提供大部分关于并发的接口和类,如BlockingQueue,Callable,ConcurrentHashMap,ExecutorService, Semaphore等。

java.util.concurrent.atomic:提供所有原子操作的类, 如AtomicInteger, AtomicLong等; 

java.util.concurrent.locks:提供锁相关的类, 如Lock, ReentrantLock, ReadWriteLock, Condition等;

 CountDownLatch

 CountDownLatch等待多个线程完成执行,这个类会等待多个子线程结束后才开始执行主线程的其他操作。直接上一个例子。

@Testpublic void testCountDown(){int count = 10;final CountDownLatch l = new CountDownLatch(count);for (int i = 0; i < count; ++i){final int index = i;new Thread(new Runnable() {@Overridepublic void run() {try {Thread.currentThread().sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("thread " + index + " has finished...");l.countDown();}}).start();}try {l.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("now all threads have finished");}
这个例子中,结束语句会在所有线程结束后再执行,否则会一直await。



Atomic类

Atomic相关类是线程安全的,支持无阻塞无锁定的操作set(),get(),getAndSet(), getAndIncrement(),getAndDecrement(),getAndAdd()



@Testpublic void testAtomic(){final int loopcount = 10000;int threadcount = 10;final NonSafeSeq seq1 = new NonSafeSeq();final SafeSeq seq2 = new SafeSeq();final CountDownLatch l = new CountDownLatch(threadcount);for(int i = 0; i < threadcount; ++i){final int index = i;new Thread(new Runnable() {@Overridepublic void run() {for(int j = 0; j < loopcount; ++j){seq1.inc();seq2.inc();}System.out.println("finished : " + index);l.countDown();}}).start();}try {l.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("both have finished....");System.out.println("NonSafeSeq:" + seq1.get());System.out.println("SafeSeq with atomic: " + seq2.get());}
class NonSafeSeq{private long count = 0;public void inc(){count++;}public long  get(){return count;}
}class SafeSeq{private AtomicLong count  = new AtomicLong(0);public void inc(){count.incrementAndGet();}public long get(){return count.longValue();}
}
输出结果如下:





both have finished....
NonSafeSeq:93212
SafeSeq with atomic: 100000
很明显看出来在原始方法中即使做了10000次相加操作也没有办法保证多线程下的一致性。使用AtomicLong进行相加可以避免这样的问题。



ReentrantLock类

之前一直是使用synchronized关键字来保证线程间的同步。concurrent包提供了ReentrantLock类,该类提供lock()和unlock()方法

1. 是更好的性能, 

2. 提供同一个lock对象上不同condition的信号通知 

3. 还提供lockInterruptibly这样支持响应中断的加锁过程,意思是说你试图去加锁,但是当前锁被其他线程hold住,然后你这个线程可以被中断;

这里直接上下相关lock操作的代码

class SafeSeqWithLock{private long count = 0;private ReentrantLock lock = new ReentrantLock();public void inc(){lock.lock();try{count++;}finally{lock.unlock();}}public long get() {return count;}}
可以看到,这里在++操作之前先lock了,然后再执行了unlock操作。



ReadWriteLock

读锁可以有很多个锁同时上锁,只要当前没有写锁; 

写锁是排他的,上了写锁,其他线程既不能上读锁,也不能上写锁;同样,需要上写锁的前提是既没有读锁,也没有写锁;

试图获得写锁的线程只有当另外一个线程将读锁释放了以后才可以获得

@Testpublic void testRWLock_getw_onr(){ReentrantReadWriteLock lock = new ReentrantReadWriteLock();final Lock rlock = lock.readLock();final Lock wlock = lock.writeLock();final CountDownLatch l  = new CountDownLatch(2);// start r threadnew Thread(new Runnable() {@Overridepublic void run() {System.out.println(new Date() + "now to get rlock");rlock.lock();try {Thread.currentThread().sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(new Date() + "now to unlock rlock");rlock.unlock();l.countDown();}}).start();// start w threadnew Thread(new Runnable() {@Overridepublic void run() {System.out.println(new Date() + "now to get wlock");wlock.lock();System.out.println(new Date() + "now to unlock wlock");wlock.unlock();l.countDown();}}).start();try {l.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(new Date() + "finished");}



总结一下。这里是concurrent包中常用的几个类。集中涉及了多线程,并发控制,锁的相关机制。



转载于:https://my.oschina.net/zimingforever/blog/143914

更多相关:

  • 菜鸟一枚,正在学习C++ Gui Qt4,整理很零碎,欢迎批评指正   1.窗口标题: QWidget *window = new QWidget; window->setWindowTitle("Enter Your Age"); **************************************** 关于标题...

  • 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 总体思路是: 比较两个链表头节点,较小的插入新链表指针之后,同时较小链表指针向后移动一位 实现如下: ListNode* mergeTwo...

  • 1.直接调用微软socket对象处理 static void Main(string[] args){try{IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });//在3721端口新建一个TcpListener对象TcpListener listener = new...

  •   现在很多地方都会用到zookeeper, 用到它的地方就是为了实现分布式。用到的场景就是服务注册,比如一个集群服务器,需要知道哪些服务器在线,哪些服务器不在线。   ZK有一个功能,就是创建临时节点,当机器启动应用的时候就会连接到一个ZK节点,然后创建一个临时节点,那么通过获取监听该路径,并且获取该路径下的节点数量就知道有哪些服务...

  • 前台到后台java时data日期类型的转化 在实体类中用@DataTimeFormat,这样设置即使传过来是空的字符串也是可以转的,要和前面传过来的格式一致,如 @XmlElement(name="BeginDate") @DateTimeFormat(pattern="yyyy-MM-dd") private Date begin...

  • 多线程有什么好处?提高CPU的利用率,更好地利用系统资源,使用Monitor类可以同步静态/实例化的方法的全部代码或者部分代码段,使用不同的同步类创建自己的同步机制。多线程指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程提升整体处理性能。多线程是指程序中包含多个执行流,即...

  • Step1:在界面主函数的构造函数中初始化多线程 auto mythread = new QThread(); //新建connect(mythread , &QThread::finished, mythread, &QObject::deleteLater);//线程运行结束后释放内存object1->moveToThread...

  • 一、thread的基本用法 参见C++使用thread类多线程编程 。 二、类外使用多线程,访问类的成员 这几种方式,新建线程都是在类外,然后通过把友元函数或者成员函数作为thread参数。 #include #include #include using namesp...

  • 本博文是根据中科大信息学院谭立湘老师的课件加上自己的理解整理出来的 ************************************************************************************ NVIDIA在2007年推出CUDA这个统一计算架构 CUDA的基本思想是支持大量的线程级并...

  • 一、parallel communication patterns   并行通信模式 Map:映射,在特定的位置读取和写入。 Gather:收集,从多个不同的位置读入,写入一个位置。 Scatter:分发,写入多个位置。 Transpose转置 结构数组缩写为AOS,数组结构缩写为SOA 转置运算是指任务重新排序内存中的数...

  • 关于Stream和Collectors的用法,这应该是总结的最全的文章了,大家可以收藏一下。一:简介java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样就可以将多个操作依次串起来。Stream...

  • 枚举类型测试代码: public class EnumTest {public static void main(String[] args) {Size s = Size.SMALL;Size t = Size.LARGE;// s和t引用同一个对象?System.out.println(s == t); //// 是原始数据类...

  • 程序设计思路:分别建立两个类:ScoreInformation类(用来定义学生的基本信息以及设置set和get函数)ScoreManagement类(用来定义实现学生考试成绩录入,考试成绩修改,绩点计算等功能的函数)和一个主函数Text类 (通过输入的数字选项进行功能的实现,因为退出系统代码量极少,所以在主函数中实现此功能) 程序源...

  • package wjf; import java.util.Scanner; public class wjf1{public static void main(String[] args){ //主方法Scanner scan=new Scanner(System.in); System.out.p...

  • 日期:2018.10.07 星期五 博客期:014   一、Java中的位运算 代码如下: 1 package Morts107; 2 3 public class Test107 { 4 public static void main(String[] args) { 5 int z; 6...