JAVA多线程进度协作

主要以下面类实现多线程相关业务场景及信号量实现场景,主要以记录为主,不足之处,敬请见谅!

CountDownLatch类方法

CountDownLatch(int count); //构造方法,创建一个值为count 的计数器。 await();//阻塞当前线程,将当前线程加入阻塞队列。 await(long timeout, TimeUnit unit);//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行, countDown();//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。

CountDownLatch类实现方式

 private static java.util.concurrent.CountDownLatch countDownLatch = new java.util.concurrent.CountDownLatch(3);

    public static void main(String[] args) {
        try {
            // 启动需要被唤醒的线程
            Thread postTaskThread = new Thread(new PostTask());
            postTaskThread.start();
            // 启动三个前置线程
            for (int i = 0; i < 3; i++) {
                Thread thread = new Thread(new Task());
                thread.start();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static class Task implements Runnable {
        public void run() {
            try {
                String threadName = Thread.currentThread().getName();
                System.out.println(threadName + " starts running.");
                // 睡眠一个随机的时间,模拟线程的执行时间差异
                Thread.sleep((long) (Math.random() * 100));
                countDownLatch.countDown();
                System.out.println(threadName + " completed.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static class PostTask implements Runnable {
        public void run() {
            try {
                String threadName = Thread.currentThread().getName();
                // 挂起,并等待唤起
                countDownLatch.await();
                // 只有当线程重新被countDownLatch唤起后,才能执行下面的语句
                System.out.println(threadName + " is activated.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
CyclicBarrier类方法 
public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)
parties 是参与线程的个数
第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务
public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
线程调用 await() 表示自己已经到达栅栏
BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时

CyclicBarrier类实现方式

   // 每一批次要凑够4个线程
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(4,new Action());

    public static void main(String[] args) {
        try {
            // 我们开启4个线程
            for (int i = 0; i < 5; i++) {
                Thread thread = new Thread(new Task());
                thread.start();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static class Task implements Runnable {
        public void run() {
            try {
                String threadName = Thread.currentThread().getName();
                Thread.sleep((long) (Math.random() * 100));
                System.out.println(threadName + " 完成第一阶段工作");
                // 到达等待节点
                System.out.println(threadName + "到达,时间是:"+ new Date().getTime() +",栅栏倒计数: " + cyclicBarrier.await());
                System.out.println(threadName + " 进入第二阶段工作");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static class Action implements Runnable {
        public void run() {
            try {
                String threadName = Thread.currentThread().getName();
                System.out.println(threadName + " 进行额外任务");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
ForkJoinPool类方法
必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制,
通常情况下我们不需要直接继承ForkJoinTask类,而只需要继承它的子类,Fork/Join框架提供了以下两个子类:
 RecursiveAction:用于没有返回结果的任务。
RecursiveTask :用于有返回结果的任务。

ForkJoinPool类实现方式

public static void main(String[] args) {
        try {
            // 创建总分线程池
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            // 计算某个数字的阶乘
            Integer num = 7;
            Future<Integer> result = forkJoinPool.submit(new ForkJoinPoolSecondTest.FactorialCalculator(num));
            System.out.println(num +"! = "+result.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class FactorialCalculator extends RecursiveTask<Integer> {
        private static final long serialVersionUID = 1L;
        private static final int THRESHOLD = 2;
        private int start;
        private int end;

        public FactorialCalculator(int end) {
            this.start = 1;
            this.end = end;
        }

        public FactorialCalculator(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        public Integer compute() {
            String threadName = Thread.currentThread().getName();
            int result = 1;
            if ((end - start) < THRESHOLD) {
                for (int i = start; i <= end; i++) {
                    result *= i;
                }
                System.out.println(threadName + "计算完成[" + start +"," + end+"]之间的乘积,得到结果为:"+result);
            } else {
                int middle = (start + end) >>> 1;
                // 进行任务的拆分与分别计算
                System.out.println(threadName + "将[" + start +"," + end+"]任务拆分为[" + start +"," + middle+"] 和 [" +  (middle+1) +"," + end+"] 两个子任务");
                ForkJoinPoolSecondTest.FactorialCalculator leftPartCalculator = new ForkJoinPoolSecondTest.FactorialCalculator(start, middle);
                ForkJoinPoolSecondTest.FactorialCalculator rightPartCalculator = new ForkJoinPoolSecondTest.FactorialCalculator(middle + 1, end);
                leftPartCalculator.fork();
                rightPartCalculator.fork();
                // 合并任务结果
                result = leftPartCalculator.join() * rightPartCalculator.join();
                System.out.println(threadName + "将[" + start +"," + middle+"] 和 [" +  (middle+1) +"," + end+"] 两个子任务的结果进行了合并,得到[" + start +"," + end+"]之间的乘积,得到结果为:"+result);
            }
            return result;
        }
    }
Semaphore类方法
Semaphore 通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。
 可以把它简单的理解成我们停车场入口立着的那个显示屏,
 每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,
 显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,
 车辆就无法进入停车场了,直到有一辆车从停车场出去为止。
 * acquire()
 * 获取一个令牌,在获取到令牌、或者被其他线程调用中断之前线程一直处于阻塞状态。
 * acquire(int permits)
 * 获取一个令牌,在获取到令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状态。
 *acquireUninterruptibly()
 * 获取一个令牌,在获取到令牌之前线程一直处于阻塞状态(忽略中断)。
 *tryAcquire()
 * 尝试获得令牌,返回获取令牌成功或失败,不阻塞线程。
 * tryAcquire(long timeout, TimeUnit unit)
 * 尝试获得令牌,在超时时间内循环尝试获取,直到尝试获取成功或超时返回,不阻塞线程。
 * release()
 * 释放一个令牌,唤醒一个获取令牌不成功的阻塞线程。
 * hasQueuedThreads()
 * 等待队列里是否还存在等待线程。
 * getQueueLength()
 * 获取等待队列里阻塞的线程数。
 * drainPermits()
 * 清空令牌把可用令牌数置为0,返回清空令牌的数量。
 * availablePermits()
 * 返回可用的令牌数量。

Semaphore类实现方式

 //停车场同时容纳的车辆10
    private  static  Semaphore semaphore=new Semaphore(10);
    public static void main(String[] args) {
        //模拟100辆车进入停车场
        for(int i=0;i<100;i++){
            Thread thread=new Thread(new Runnable() {
                public void run() {
                    try {
                        System.out.println("===="+Thread.currentThread().getName()+"来到停车场");
                        if(semaphore.availablePermits()==0){
                            System.out.println("车位不足,请耐心等待");
                        }
                        semaphore.acquire();//获取令牌尝试进入停车场
                        System.out.println(Thread.currentThread().getName()+"成功进入停车场");
                        Thread.sleep(new Random().nextInt(10000));//模拟车辆在停车场停留的时间
                        System.out.println(Thread.currentThread().getName()+"驶出停车场");
                        semaphore.release();//释放令牌,腾出停车场车位
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },i+"号车");
            thread.start();

        }

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值