Java并发编程的艺术笔记(八)

8. Java中的并发工具类

提供并发流程控制

  • CyclicBarrier
  • CountDownLatch
  • Semaphore

线程间交换数据

  • Exchanger

1. CountDownLatch

CountDownLatch允许一个或多个线程等待其他线程完成操作,类似于一个计数器。构造参数会传入一个N值,当调用CountDownLatch的countDown方法,N就会-1,await方法会阻塞当前线程,直到N等于0。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {

    static CountDownLatch count = new CountDownLatch(5) ;

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0 ; i<5 ; i++){
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    count.countDown();
                    count.countDown();
                }
            } , "thread"+i) ;
            t.start();
        }
        count.await();
        System.out.println("main thread");
    }
}

thread1
thread4
thread2
111
thread3
thread0

2. CyclicBarrier

让一组线程达到一个屏障(同步点)阻塞,直到最后一个线程屏障时,所有被屏障拦截的线程才会继续运行。

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

public class CyclicBarrierTest {

    static CyclicBarrier c = new CyclicBarrier(5, new Runnable() {

        @Override
        public void run() {
            System.out.println("thread c ");
        }
    }) ;

    public static void main(String[] args) {
        for (int i=0 ; i<10; i++){
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                    try {
                        c.await() ;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            } , "thread-"+i) ;
            t.start();
        }


    }
}

thread-0
thread-2
thread-3
thread-6
thread-7
thread c
thread-1
thread-4
thread-5
thread-8
thread-9
thread c

可见执行了两遍(一组5个线程)

CyclicBarrier应用场景:多线程计算数据、合并计算结果的场景。


import java.util.Map;
import java.util.concurrent.*;

public class BankWaterService implements Runnable{

    private CyclicBarrier c = new CyclicBarrier(4 ,this) ;

    private Executor executor = Executors.newFixedThreadPool(4) ;

    private ConcurrentHashMap<String , Integer> sheetBankWaterCount = new ConcurrentHashMap<>() ;

    private void count(){
        for (int i=0 ; i<4 ; i++){

            executor.execute(new Runnable() {
                @Override
                public void run() {
                    sheetBankWaterCount.put(Thread.currentThread().getName() , 1) ;
                    try {
                        c.await() ;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println("结束");
                }
            });
        }
    }

    @Override
    public void run() {
        int result = 0 ;
        for (Map.Entry<String,Integer> entry : sheetBankWaterCount.entrySet()) {
            result += entry.getValue() ;
        }
        sheetBankWaterCount.put("result" , result) ;
        System.out.println(result);
    }

    public static void main(String[] args) {
        BankWaterService bankWaterService = new BankWaterService() ;

        bankWaterService.count();
    }
}

4
结束
结束
结束
结束

3. Semaphore

用来控制同时访问特定资源的线程数量,通过协调各个资源,保证合理的使用公共资源。Semaphore可以用做流量控制,比如数据库连接等等。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    private static final int THREAD_COUNT = 30 ;

    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT) ;
	//10为许可证的数量,表示最大并发线程数为10
    
    private static Semaphore s = new Semaphore(10) ;

    public static void main(String[] args) {
        for (int i=0 ; i<THREAD_COUNT ; i++){
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        //获得许可证
                        s.acquire();
                        System.out.println("save data");
                        //归还许可证
                        s.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        threadPool.shutdown();
    }
}
  • intavailablePermits():返回信号量中当前可用的许可证数
  • intgetQueueLength():返回正在等待获取许可证的线程数
  • booleanhasQueuedThreads():是否有线程正在等待获取许可证
  • protented void reducePermits(int reduction):减少reduction个许可证
  • protented Collection getQueuedThreads():返回所有等待获取许可证的线程集合

4. Exchanger

Exchanger它提供一个同步点,用于进行线程间的数据交换,如果第一个线程先执行exchange方法,它会等待第二个线程也执行exchange方法,当两个线程到达同步点后,就可以交换数据。如果有一个线程没执行exchange方法,则一直等待下去。

  • 遗传算法
  • 校对工作

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {

    private static final Exchanger<String> exgr = new Exchanger<>() ;

    private static ExecutorService service = Executors.newFixedThreadPool(2) ;

    public static void main(String[] args) {
        service.execute(new Runnable() {
            @Override
            public void run() {
                String a = "银行流水帐a" ;
                try {
                    exgr.exchange(a) ;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        service.execute(new Runnable() {
            @Override
            public void run() {
                String b = "银行流水帐b" ;
                String a = null ;
                try {
                    a = exgr.exchange("B") ;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(a.equals(b));
                System.out.println(a);
                System.out.println(b);
            }
        });

        service.shutdown();
    }
}

false
银行流水帐a
银行流水帐b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值