码迷,mamicode.com
首页 > 编程语言 > 详细

java并发工具类

时间:2020-09-17 12:27:29      阅读:33      评论:0      收藏:0      [点我收藏+]

标签:共享   tps   tac   方法   ant   get   nan   eem   thread   

一、CountDownLatch

字面意思:倒计时锁闩,该类可以实现一个线程在等其他多个线程执行完之后,继续执行。

入参是一个计数器的值,当一个线程执行完毕时调用countDown()方法,计数器值会减1,当计数器值为0时,被await()阻塞的线程将被唤醒。

CountDownLatch latch = new CountDownLatch(10);

大家都玩过王者荣耀的5V5排位吧,当己方5个人准备就绪,对方5人也准备就绪时,才可以进入B/P环节,也就是王者荣耀这个线程需要等待10位玩家的线程都准备完毕,然后才出发进入游戏的操作。

package com.duchong.concurrent;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 模拟5V5排位,10个玩家都准备就绪,才开始进入游戏
 * CountDownLatch :阻塞主线程,等子线程完成
 * @author DUCHONG
 * @since 2020-09-03 17:43:13
 */
public class CountDownLatchDemo {


    public static final int playerNum=10;

    public static void main(String[] args) {

        final CountDownLatch latch = new CountDownLatch(10);

        GameThread subThread = new GameThread(latch);
        try {

            //模拟5V5排位
            for (int i = 1; i <= playerNum; i++) {
                new Thread(subThread,"player-"+i).start();
                TimeUnit.SECONDS.sleep(1L);
            }
            //阻塞主线程
            latch.await();
        }
        catch (InterruptedException e) {
        }

        System.out.println("王者荣耀:玩家全部准备就绪,开始进入游戏");
    }


    /**
     * 游戏子线程
     */
    static class GameThread implements Runnable {

        private CountDownLatch latch;

        public GameThread(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {

            try {
                System.out.println(Thread.currentThread().getName()+"---准备就绪");
            }
            finally {
                latch.countDown();
            }
        }
    }
}

结果

技术图片

二、CyclicBarrier

字面意思: 循环屏障,多个线程到达一个屏障点时被阻塞,直到最后一个线程到达屏障点时,屏障才会解除,所有被屏障拦截的线程继续运行。

第一个入参代表屏障接触时阻塞线程的数量。第二个入参代表屏障解除时要进行的操作

CyclicBarrier c = new CyclicBarrier(10, ()->System.out.println("屏障解除"));

await()方法其实是调用Conditionawait()

public class CyclicBarrier {
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();

    //....省略
    public int await() throws InterruptedException, BrokenBarrierException {
            try {
                return dowait(false, 0L);
            } catch (TimeoutException toe) {
                throw new Error(toe); // cannot happen
            }
        }

    //wait方法
    private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
    TimeoutException {
        //重入锁
        final ReentrantLock lock = this.lock;
        //加锁
        lock.lock();
        try {
            final Generation g = generation;

            if (g.broken)
                throw new BrokenBarrierException();

            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }

            int index = --count;
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    ranAction = true;
                    nextGeneration();
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }

            // 循环
            for (;;) {
                try {
                    if (!timed)
                        // 调用condition的await()方法
                        trip.await();
                    else if (nanos > 0L)
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    if (g == generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } else {
                        // We‘re about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        Thread.currentThread().interrupt();
                    }
                }

                if (g.broken)
                    throw new BrokenBarrierException();

                if (g != generation)
                    return index;

                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
            //解锁
            lock.unlock();
        }
    }
    //....省略
}

该类同样可以实现与CountDownLatch相同的效果

package com.duchong.concurrent;

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

/**
 * 模拟5V5排位,10个玩家都准备就绪,才开始进入游戏
 * CyclicBarrier :阻塞子线程,当等待中的子线程数到达一定数量时,跳闸。
 * @author DUCHONG
 * @since 2020-09-03 17:41:35
 */
public class CyclicBarrierDemo {

    public static final int playerNum=10;
    /**
     * 屏障,初始10 当await()的线程数量达到10时,跳闸。
     */
    static CyclicBarrier c = new CyclicBarrier(playerNum, ()->System.out.println("王者荣耀:玩家全部准备就绪,开始进入游戏"));


    public static void main(String[] args) {

        try {
            //
            for (int i = 1; i <= playerNum; i++) {
                new Thread(new GameThread(),"player-"+i).start();
                TimeUnit.SECONDS.sleep(1L);
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 游戏子线程
     */
    static class GameThread implements Runnable {

        @Override
        public void run() {

            try {
                System.out.println(Thread.currentThread().getName()+"---准备就绪");
                //阻塞子线程
                c.await();

                System.out.println(Thread.currentThread().getName()+"---进入游戏");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

        }
    }

}

结果

技术图片

三、Semaphore

字面意思:信号量,多个线程访问一个共享资源时,如果想控制对该资源访问的线程的数量,可以用这个工具类。

入参对象是一个许可的数量,如果数量大于1,则可以作为共享锁来使用,如果数量等于1,则可以作为排他锁来使用

acquire()方法表示得到一个许可,可以对共享资源进行操作, 如果许可数量分配完了,其他线程将阻塞, 直到已得到许可的线程释放许可后,才有机会再获取许可。

release()方法表示释放一个许可。

Semaphore semaphore=new Semaphore(5);

接着王者荣耀排位5V5的例子来讲,当玩家进入B/P环节,5个人,但是地图只有上中下三路,也就是说最多2个人去打野位置

package com.duchong.concurrent;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * 模拟进入5V5排位游戏后的B/P环节,五个人,上中下三路,最多2个人去打野位置
 * Semaphore,对资源的并发数控制
 * @author DUCHONG
 * @since 2020-09-03 15:46
 **/
public class SemaphoreDemo {

    //打野人数
    public static final int wildNum=2;
    //总共人数
    public static final int totalNum=5;

    static Semaphore semaphore=new Semaphore(wildNum);

    public static void main(String[] args) {

        try {
            for (int i = 1; i <=totalNum; i++) {

                new Thread(new GameThread(semaphore),"player-"+i).start();
                TimeUnit.SECONDS.sleep(1L);
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    /**
     * 游戏子线程
     */
    static class GameThread implements Runnable {

        private Semaphore semaphore;

        public GameThread(Semaphore semaphore){
            this.semaphore=semaphore;
        }
        @Override
        public void run() {

            try {
                //抢到打野位置,最多两个人,其他人想选打野位时阻塞,除非抢到的人选择其他路
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName()+"---抢到打野位");

                TimeUnit.SECONDS.sleep(3L);
                System.out.println(Thread.currentThread().getName()+"---犹豫了一下,选择了其他路");
            }
            catch (Exception e){

            }
            finally {
                //新增一个许可
                semaphore.release();
            }

        }
    }
}

结果

技术图片

同一时刻只有两个player获取到打野位置(共享资源)符合预期。

java并发工具类

标签:共享   tps   tac   方法   ant   get   nan   eem   thread   

原文地址:https://www.cnblogs.com/geekdc/p/13610451.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!