JDK并发工具类讲解

1.CountDownLatch从概括到实战

CountDownLatch:从理论上来讲他是个计数器,但我们程序员更喜欢叫他发令枪,他的作用是让子线程跟主线程同步执行的一个发令枪,小伙伴们如果没有理解可以看下面实战部分

实战:

注意事项:

1.CountDownLatch的初始化计数可以随意设置,只需要后期在线程中控制减到0即刻,不是必须要跟线程数设置一致,可以通过代码灵活减去

自己想出一个需求:

现在我有一个团队,他们干啥啥不行,吃饭第一名
我要罚团队中的每个人跑两圈步,跑完再次集合解散

具体代码:

public class CountDownLatchMain {

    //这里的计算初始化计算数可以随意设置,只需要后期在线程中控制减到0即刻,
    //可以跟线程数设置不一致没关系的
    static CountDownLatch startingGun=new CountDownLatch(8);


    static class work implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"跑完第一圈");
            startingGun.countDown();
            System.out.println(Thread.currentThread().getName()+"跑完第二圈");
            startingGun.countDown();
        }
    }

    /** 团队挨罚案例 **/
    public static void main(String[] args)
            throws InterruptedException {

        new Thread(new work(),"小明").start();
        new Thread(new work(),"小张").start();
        new Thread(new work(),"小王").start();
        new Thread(new work(),"小狗").start();
        startingGun.await();
        System.out.println("全部挨罚完毕,全体都有解散!");
    }


}

运行结果:

在这里插入图片描述

2.CyclicBarrier从概括到实战

CyclicBarrier:这个工具类是个循环屏障,具体作用让等待线程全部到齐再继续往下执行,并将全部到齐还可以调用统计方法,以及还可以创建多个屏障循环执行,小伙伴们如果没有理解可以看下面实战部分

实战:

注意事项:

1.CyclicBarrier设定的等待触发的线程数要跟目前线程数一致,要不然会出现线程执行完了,CyclicBarrier还处于屏障阻塞阶段

自己想出一个需求:

喜羊羊与灰太狼大家庭准备去长沙南站做高铁
首先需要在高铁站等待人齐并且统计人是否齐全
人齐了之后去买票进高铁站
然后上高铁列车时再次统计人是否齐全
人齐了开始上高铁列车

具体代码:

public class CyclicBarrierMain {


    //注意一点CyclicBarrier设定的等待触发的线程数要跟目前线程数一致,
    //要不然会出现线程执行完了,CyclicBarrier还处于屏障阻塞阶段
    static  CyclicBarrier cyclicBarrier=new CyclicBarrier(4,new sum());


    //汇报人数,人员是否到齐
    static class sum implements Runnable{
        @Override
        public void run() {
            System.out.println("伙伴们我们人员到齐了,确认无误!");
        }
    }


    static  class work implements Runnable{
        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName()+",已经来到了长沙南站!");
                //统计人数是否齐全,等待人齐我们在一起买票进入高铁
                cyclicBarrier.await();
                System.out.println(Thread.currentThread().getName()+",已经买票进入高铁站!");
                //再次统计人数是否齐全,等待人齐我们在一起进入列车准备本次的旅途
                cyclicBarrier.await();
                System.out.println(Thread.currentThread().getName()+",已经坐上列车,本次G-67列车准备出发,祝大家本次乘坐愉快!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {

        new Thread(new work(),"喜羊羊").start();
        new Thread(new work(),"懒羊羊").start();
        new Thread(new work(),"小灰灰").start();
        new Thread(new work(),"灰太狼").start();

    }





}

运行结果:

在这里插入图片描述

3.Exchange从概括到实战

Exchange:这个工具类是个两个线程互换数据的一个数据交换所,一般实际项目中用的不多,因为有局限性只能同时让两个线程数据互换

实战:

自己想出一个需求:

小明本来没有犯法,是个好人
小霸王犯了法要坐牢,是个坏人
此时小霸王以小明家人做威胁,逼迫小明去帮小霸王坐牢

具体代码:

public class ExchangeMain {

    //定义ExChanger线程交换数据对象
    private static Exchanger<String> exchanger=new Exchanger<>();

    public static void main(String[] args) {

        new Thread(()->{
            try {
                //小明的数据
                String str=":我不认罪,我没有杀人,冤枉啊!";
                //线程交换数据
                str=exchanger.exchange(str);
                //获取数据交换后的数据
                System.out.println(Thread.currentThread().getName()+str);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"小明").start();

        new Thread(()->{
            try {
                //小霸王的数据
                String str=":我认罪,人就是我杀的,枪毙我啊!";
                //线程交换数据
                str=exchanger.exchange(str);
                //获取数据交换后的数据
                System.out.println(Thread.currentThread().getName()+str);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"小霸王").start();

    }

}

运行结果:

在这里插入图片描述

4.Callable,Future和FutureTask从概括到实战

Future:是一个接口定义了用来管理任务的一些取消,任务的结果获取等待的一个接口

FutureTask: FutureTask就继承了Future实现了Future的接口,作用一个有返回结果集的线程任务

Callable:有返回结果集的任务定义,跟FutureTask一起使用

其实小伙伴们只需要知道这个Future这个东西就是为了弥补多线程没有返回结果集的一个工具类

实战:

自己想出一个需求:

模拟现实场景,比如微服务,我有3个系统每个系统是独立的,不同的
现在我要去
系统A拿出一个数据10
系统B拿出一个数据20
系统C拿出一个数据30
并且中断系统A任务,
最后在主线程进行B,C合并统计

具体代码:

public class FutureMain {


    public static void main(String[] args)
            throws Exception{

        FutureTask<Integer>  systemATask=new FutureTask(()->{
            //具体Callable返回
            while (true){
                if(Thread.currentThread().isInterrupted()){
                    System.out.println("获取系统A任务已经被终止!");
                    return 0;
                }
            }
        });

        FutureTask<Integer>  systemBTask=new FutureTask(()->{
            //具体Callable返回
            return 20;
        });

        FutureTask<Integer>  systemCTask=new FutureTask(()->{
            //具体Callable返回
            return 30;
        });

        new Thread(systemATask).start();
        new Thread(systemBTask).start();
        new Thread(systemCTask).start();


        //中断系统A任务,内部采用线程协调模式终止
        Thread.sleep(300);
        systemATask.cancel(true);

        int sum=systemBTask.get()+systemCTask.get();

        System.out.println("成功获取了各自系统中的数据,合计结果为:"+sum);


    }


}

运行结果:

在这里插入图片描述

5.Semaphore从概括到实战

Semaphore:这个是个信息量管理器,他就跟我们项目中经常用到的数据库连接池一样,比如我数据库最大连接数只能同时存在10个线程,然后此时我有20个线程同时获取数据库连接,肯定是我这20个线程中只能有10个线程可以拿到数据库连接,其余的10个线程则需要等待当前正在10个正在使用数据库连接的线程归还才可以拿到数据库连接池,这个Semaphore的概念跟数据库连接池差不多.

自己想出一个需求:

实战:

注意事项:

1.Semaphore的归还这里有个坑就是归还的时候可以无限归还,小伙伴们记得控制一下

自己想出一个需求:

使用semaphore实现简单的数据库连接池
涉及到底层方面的套件字连接数据库不管他,只弄个最简单的演示

具体代码:

public class SqlConnection implements Connection {
    @Overrid
    public void commit() throws SQLException {
        //模拟事务提交
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public class SemaphoreMain {

    static class SemaphoreDBPool{

        LinkedList<Connection> connections=new LinkedList<>();

        //这里我用了两个Semaphore是因为这里有个坑,使用Semaphore归还许可证时可以无限归还
        //所以设置范围区间,只能在这个范围区间活动
        Semaphore max,min;

        public void initializePoolSize(int size){
            max=new Semaphore(size);
            min=new Semaphore(0);
            while (size>0){
                connections.addLast(new SqlConnection());
                --size;
            }
        }


        public Connection getConnection()
                throws InterruptedException {
            //交叉扭转范围区间逻辑
            max.acquire();
            Connection connection;
            synchronized (connections){
                connection=connections.removeFirst();
            }
            min.release();
            return connection;
        }

        public void returnConnection(Connection connection)
                throws InterruptedException {
            //交叉扭转范围区间逻辑
            min.acquire();
            synchronized (connections){
                connections.addLast(connection);
            }
            max.release();
        }

    }


    static class work implements Runnable{

        SemaphoreDBPool semaphoreDBPool;

        public work(SemaphoreDBPool semaphoreDBPool) {
            this.semaphoreDBPool = semaphoreDBPool;
        }

        @Override
        public void run() {
            try {
                Connection connection=semaphoreDBPool.getConnection();
                System.out.println(Thread.currentThread().getName()+"线程,已经拿到数据库连接!");
                connection.commit();
                semaphoreDBPool.returnConnection(connection);
                System.out.println(Thread.currentThread().getName()+"线程,已经归还数据库连接!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }


    public static void main(String[] args) {

        SemaphoreDBPool semaphoreDBPool=new SemaphoreDBPool();
        //设置10个连接池数量
        semaphoreDBPool.initializePoolSize(10);
        //启动20个线程获取数据库连接
        for (int i = 0; i < 20; ++i) {
            new Thread(new work(semaphoreDBPool),"线程"+(i+1)).start();
        }

    }

}

运行结果:
在这里插入图片描述
有问题的小伙伴们,欢迎提问

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值