《Java并发编程的艺术》读书笔记—— 并发工具

                              并发工具

1.CountDownLatch

          在线程协同时,经常会使用线程的join方法,join方法是阻塞当前线程等待join的线程执行完,在join方法内部是在while循环中不断地检查join的线程是否存活,如果存活的话就wait(0),直到join的线程中止后会调用this.notifyAll()方法来唤醒wait的线程。CountDownLatch类提供了类似的功能。
         CountDownLatch构造器传入一个整型变量,然后调用CountDownLatch.await就会阻塞当前线程,每次调用countDown方法都会让这个变量减1,当减为0时被await阻塞的线程就会被唤醒。这样,我们在一个线程中await,然后把CountDownLatch对象传入另外的线程中,就可以实现线程的等待协同。
        下面是一个用一个线程生产100个Object对象存入List集合中的CountDownLatch使用例子,当生产了10个Object对象时唤醒被await的线程。
 package study.threadutil;


import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;


public class CountDownLatchTest {
private static List<Object> list = new CopyOnWriteArrayList();


private static class MyThread extends Thread {
private CountDownLatch cdl;


public MyThread(CountDownLatch c) {
this.cdl = c;
}


@Override
public void run() {
for (int i = 0; i < 100; i++) {
list.add(new Object());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("product " + i + " object");
cdl.countDown();
}
}
}


public static void main(String[] args) {
CountDownLatch cdl = new CountDownLatch(10);
new MyThread(cdl).start();
try {
cdl.await();
System.out.println("get up");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


执行结果如下:
product 0 object
product 1 object
product 2 object
product 3 object
product 4 object
product 5 object
product 6 object
product 7 object
product 8 object
product 9 object
get up
product 10 object
product 11 object
product 12 object
product 13 object
product 14 object
product 15 object
product 16 object
product 17 object
product 18 object
product 19 object
product 20 object
product 21 object

2.CyclicBarrier

        同步屏障的作用是把线程阻塞在一个屏障点,直到所有线程都到达时才统一放行,这就相当于那种团队使用游戏,只有所有人都到达某个门时门才能打开一样。
       下面是一个使用CycliBarrier来实现三个线程(有一个是主线程)来消费20个数字,每个线程消费10个数字
package study.threadutil;


import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;


public class CyclicBarrierTest {
private static CyclicBarrier cb;


private static class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread() + "" + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread() + " finished");
}
}


public static void main(String[] args) {
cb = new CyclicBarrier(3);
new MyThread().start();
new MyThread().start();
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread() + " finished");
}
}
执行结果如下:

Thread[Thread-0,5,main]0
Thread[Thread-1,5,main]0
Thread[Thread-0,5,main]1
Thread[Thread-1,5,main]1
Thread[Thread-1,5,main]2
Thread[Thread-0,5,main]2
Thread[Thread-1,5,main]3
Thread[Thread-0,5,main]3
Thread[Thread-1,5,main]4
Thread[Thread-0,5,main]4
Thread[Thread-1,5,main]5
Thread[Thread-0,5,main]5
Thread[Thread-1,5,main]6
Thread[Thread-0,5,main]6
Thread[Thread-1,5,main]7
Thread[Thread-0,5,main]7
Thread[Thread-1,5,main]8
Thread[Thread-0,5,main]8
Thread[Thread-1,5,main]9
Thread[Thread-0,5,main]9
Thread[main,5,main] finished
Thread[Thread-1,5,main] finished
Thread[Thread-0,5,main] finished

CyclicBarrier实现的功能和CountDownLatch差不多,不过CyclicBarrier可以通过reset方法来重置记数器,可以复用,因此CyclicBarrier的适用场景更多。CyclicBarrier还可以通过getNumberWaiting方法来获取等待的线程的数量,通过isBroken来得到阻塞的线程是否被中断。

3.Semaphore

            好好学过操作系统的都不会忘记Semaphore,在操作系统进程资源分配的时候,经常用Semaphore信号量来控制资源的获取进程数,防止死锁。而Semaphore类跟操作系统中学到的信号量具有同样的功能,也是提供了acquire和release两个方法来控制资源的获取与释放。同时Semaphore还提供了intavailablePermits方法用来返回还剩多少可用资源,intgetQueueLength方法用来返回正在等待获取资源的线程数,booleanhasQueuedThreads方法用来返回是否有线程正在等待获取资源,reducePermits方法用来减少资源,getQueuedThreads方法用来返回所有等待获取资源的线程集合,但这个方法是个protected方法。、
        下面是一个信号量使用的例子,在例子中,有三个资源,30个线程,通过信号量来协同线程。
package study.threadutil;


import java.util.concurrent.Semaphore;


public class SemaphoreTest {
private static Semaphore sp;


private static class MyThread extends Thread {
@Override
public void run() {
try {
sp.acquire();
System.out.println(Thread.currentThread() + " after acquire resource");
Thread.sleep(100);
System.out.println(Thread.currentThread() + " before release resource");
sp.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


}


public static void main(String[] args) {
sp = new Semaphore(3);
for (int i = 0; i < 10; i++) {
new MyThread().start();
}
}
}

执行结果如下:
Thread[Thread-0,5,main] after acquire resource
Thread[Thread-2,5,main] after acquire resource
Thread[Thread-1,5,main] after acquire resource
Thread[Thread-1,5,main] before release resource
Thread[Thread-0,5,main] before release resource
Thread[Thread-2,5,main] before release resource
Thread[Thread-4,5,main] after acquire resource
Thread[Thread-3,5,main] after acquire resource
Thread[Thread-5,5,main] after acquire resource
Thread[Thread-4,5,main] before release resource
Thread[Thread-5,5,main] before release resource
Thread[Thread-3,5,main] before release resource
Thread[Thread-7,5,main] after acquire resource
Thread[Thread-6,5,main] after acquire resource
Thread[Thread-8,5,main] after acquire resource
Thread[Thread-7,5,main] before release resource
Thread[Thread-6,5,main] before release resource
Thread[Thread-8,5,main] before release resource
Thread[Thread-9,5,main] after acquire resource
Thread[Thread-9,5,main] before release resource


4.Exchanger

最后一个是Exchanger线程交换数据的工具类,这个工具类提供了一个exchange方法,通过这个方法,会阻塞当前线程并等待另一个线程也执行exchange方法,当两个线程都执行了exchange方法后,就会返回对方所传入的参数。
下面是一个两个线程通信查看对方传输过来的数的例子
package study.threadutil;


import java.util.concurrent.Exchanger;


public class ExchangerTest {
private static Exchanger<Long> ex;


private static class MyThread extends Thread {
@Override
public void run() {
long id = Thread.currentThread().getId();
System.out.println(Thread.currentThread() + ": my id is" + id);
try {
long youId = ex.exchange(id);
System.out.println(Thread.currentThread() + ": your id is " + youId);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


public static void main(String[] args) {
ex = new Exchanger();
new MyThread().start();
new MyThread().start();
}
}


执行结果如下:
Thread[Thread-1,5,main]: my id is13
Thread[Thread-0,5,main]: my id is12
Thread[Thread-0,5,main]: your id is 13
Thread[Thread-1,5,main]: your id is 12
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值