线程中的同步工具类

线程中常用的一些同步工具类:

  1. 阻塞队列
  2. 信号量(Semaphore)
  3. 栅栏(Barrier)
  4. 闭锁(Latch)

Semaphore

注意点

获得一项前,每个线程必须从信号量获取许可,从而保证可以使用该项。该线程结束后,将项返回到池中并将许可返回到该信号量,从而允许其他线程获取该项。注意,调用 acquire() 时无法保持同步锁,因为这会阻止将项返回到池中。信号量封装所需的同步,以限制对池的访问,这同维持该池本身一致性所需的同步是分开的。

示例

public class SemaphoreTest {

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(4);

        // 创建一个Semaphore信号量,并设置最大并发数为3
        final Semaphore sp = new Semaphore(3);

        // 创建10个任务,上面的缓存线程池就会创建10个对应的线程去执行
        for (int index = 0; index < 10; index++) {
            final int NO = index;
            Runnable run = () -> {
                try {
                    // 获取许可
                    sp.acquire();
                    System.out.println(Thread.currentThread().getName() + "获取许可" + "(" + NO + ")," + "剩余:" + sp.availablePermits());
                    Thread.sleep(10000);
                    // 释放许可
                    sp.release();
                    System.out.println(Thread.currentThread().getName() + "释放许可" + "(" + NO + ")," + "剩余:" + sp.availablePermits());
                } catch (InterruptedException e) {
                    System.out.println("InterruptedException:" + e);
                }
            };
            service.execute(run);
        }
        // 关闭线程池
        service.shutdown();
    }
}

CountDownLatch

示例:

public class Test {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(3);

        // 继承Thread类
        new Thread(){
            @Override
            public void run() {
                try {
                    System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
                    Thread.sleep(3000);
                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
                    latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        }.start();

        new Thread(){
            @Override
            public void run() {
                try {
                    System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
                    Thread.sleep(3000);
                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
                    latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        }.start();

        // 实现Runnable接口
        ((Runnable) () -> {
            try {
                System.out.println("Runnable");
                Thread.sleep(3000);
                System.out.println("Runnable执行完毕");
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).run();

        try {
            System.out.println("等待2个子线程执行完毕...");
            latch.await();
            System.out.println("2个子线程已经执行完毕");
            System.out.println("继续执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

CyclicBarrier

需要可重用的 CountDownLatch,考虑使用 CyclicBarrier。

public class Athlete implements Runnable {
    private CyclicBarrier cyclicBarrier;
    private String name;

    public Athlete(CyclicBarrier cyclicBarrier, String name) {
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + ",就位");
        try {
            cyclicBarrier.await();
            Random random = new Random();
            double time = random.nextDouble() + 9;
            Thread.sleep(1000L);
            System.out.println(name + ":" + time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

public class Race {
    Executor executor = Executors.newFixedThreadPool(8);
    private CyclicBarrier cyclicBarrier = new CyclicBarrier(8);

    public void start() {
        List<Athlete> athleteList = new ArrayList<>(16);
        athleteList.add(new Athlete(cyclicBarrier, "博尔特"));
        athleteList.add(new Athlete(cyclicBarrier, "鲍威尔"));
        athleteList.add(new Athlete(cyclicBarrier, "盖伊"));
        athleteList.add(new Athlete(cyclicBarrier, "布雷克"));
        athleteList.add(new Athlete(cyclicBarrier, "加特林"));
        athleteList.add(new Athlete(cyclicBarrier, "苏炳添"));
        athleteList.add(new Athlete(cyclicBarrier, "路人甲"));
        athleteList.add(new Athlete(cyclicBarrier, "路人乙"));
        for (Athlete athlete : athleteList) {
            executor.execute(athlete);
        }
    }

    public static void main(String[] args) {
        Race race = new Race();
        race.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值