leetcode并发题解
按序打印

解法一:使用volatile
public class FooWithVolatile {
    private volatile int count;
    public FooWithVolatile() {
    }
    public void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        count++;
    }
    public void second(Runnable printSecond) throws InterruptedException {
        // printSecond.run() outputs "second". Do not change or remove this line.
        while(count != 1) { }
        printSecond.run();
        count++;
    }
    public void third(Runnable printThird) throws InterruptedException {
    	while(count != 2) { }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}
类似的,我们也可以使用AtomicInteger,不过其实AtomicInteger底层也是使用了volatile字段,只不过在计算时会使用CAS解决原子性问题,但是这里的while循环对自增操作进行了阻塞,所以不会出现三个线程同时对count自增的情况,所以没必要使用AtomicInteger,更何况CAS操作里面的while循环也是很耗费资源的
解法二:使用CountDownLatch
public class FooWithCountDownLatch {
    private CountDownLatch second = new CountDownLatch(1);
    private CountDownLatch third = new CountDownLatch(1);
    public FooWithCountDownLatch() {
    }
    public void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        second.countDown();
    }
    public void second(Runnable printSecond) throws InterruptedException {
    	second.await();
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        third.countDown();
    }
    public void third(Runnable printThird) throws InterruptedException {
    	third.await();
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}
类似的,这里我们使用两个“门栓”栓住(阻塞)second方法和third方法执行run方法打印结果,当first方法执行完毕后,释放second的门栓让second方法打印结果,second方法执行完毕后,释放third的门栓让third方法打印结果
交替打印FooBar

class FooBarWithCountDownLatch {
    private int n;
    private CountDownLatch fooLatch = new CountDownLatch(0);
    private CountDownLatch barLatch = new CountDownLatch(1);
    public FooBarWithCountDownLatch(int n) {
        this.n = n;
    }
    public void foo(Runnable printFoo) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            fooLatch.await();
            // printFoo.run() outputs "foo". Do not change or remove this line.
            printFoo.run();
            fooLatch = new CountDownLatch(1);
            barLatch.countDown();
        }
    }
    public void bar(Runnable printBar) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            barLatch.await();
            // printBar.run() outputs "bar". Do not change or remove this line.
            printBar.run();
            barLatch = new CountDownLatch(1);
            fooLatch.countDown();
        }
    }
}
这里要注意,CountDownLatch和CyclicBarrier不一样,CountDownLatch是一次性的,countDown到0之后不会自己恢复成1,所以要每次new一个CountDownLatch对象。
打印零与奇偶数

public class ZeroEvenOdd {
    private int n;
    private CountDownLatch zero = new CountDownLatch(0);
    private CountDownLatch even = new CountDownLatch(1);
    private CountDownLatch odd = new CountDownLatch(1);
    public ZeroEvenOdd(int n) {
        this.n = n;
    }
    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero(IntConsumer printNumber) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            zero.await();
            printNumber.accept(0);
            zero = new CountDownLatch(1);
            if(i % 2 == 0) {
                odd.countDown();
            } else {
                even.countDown();
            }
        }
    }
    public void even(IntConsumer printNumber) throws InterruptedException {
        for (int i = 2; i < n; i+=2) {
            even.await();
            printNumber.accept(i);
            even = new CountDownLatch(1);
            zero.countDown();
        }
    }
    public void odd(IntConsumer printNumber) throws InterruptedException {
        for (int i = 1; i < n; i+=2) {
            odd.await();
            printNumber.accept(i);
            odd = new CountDownLatch(1);
            zero.countDown();
        }
    }
}
这道题没什么好说的,做法也同样很多样,只要仔细点,都可以做对,但是我感觉都没直接用CoutDownLatch好。
H2O

public class H2O {
    private Semaphore hSemaphore = new Semaphore(2);
    private Semaphore oSemaphore = new Semaphore(0);
    public H2O() {
    }
    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
        hSemaphore.acquire();
        // releaseHydrogen.run() outputs "H". Do not change or remove this line.
        releaseHydrogen.run();
        oSemaphore.release();
    }
    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        oSemaphore.acquire(2);
        // releaseOxygen.run() outputs "H". Do not change or remove this line.
        releaseOxygen.run();
        hSemaphore.release(2);
    }
}
实在想不到Semaphore以外的做法,虽然看题解确实有,但是反而不怎么好
leetcode并发题解的更多相关文章
- LeetCode OJ 题解
		博客搬至blog.csgrandeur.com,cnblogs不再更新. 新的题解会更新在新博客:http://blog.csgrandeur.com/2014/01/15/LeetCode-OJ-S ... 
- Leetcode 简略题解 - 共567题
		Leetcode 简略题解 - 共567题 写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ... 
- LeetCode 算法题解 js 版 (001 Two Sum)
		LeetCode 算法题解 js 版 (001 Two Sum) 两数之和 https://leetcode.com/problems/two-sum/submissions/ https://lee ... 
- leetcode & lintcode 题解
		刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ... 
- LeetCode一句话题解
		深度优先搜索 人生经验 1. 需要输出所有解.并由于元素集有重复元素,要求返回的结果需要去重的情况,可考虑使用值对应数量的map,然后分别考虑依次取不同数量该值的可能. LeetCode39 题目:给 ... 
- [leetcode] 位操作题解
		子集 题目[78]:给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 示例: 输入: nums = [1,2,3] 输出: [ [3], [1], [2], [ ... 
- LeetCode 中等题解(3)
		34 在排序数组中查找元素的第一个和最后一个位置 Question 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂 ... 
- LeetCode 中等题解(1)
		16 最接近的三数之和 Question 给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 nums 中的三个整数,使得它们的和与 target 最接近.返回这三个数的和. ... 
- leetcode个人题解——two sum
		这是leetcode第一题,通过较为简单. 第一题用来测试的,用的c,直接暴力法过, /** * Note: The returned array must be malloced, assume c ... 
随机推荐
- 用ABAP 生成二维码 QR Code
			除了使用我的这篇blogStep by step to create QRCode in ABAP Webdynpro提到的使用ABAP webdynpro生成二维码之外,也可以通过使用二维码在线生成 ... 
- Python 绘图 - Bokeh 柱状图小试(Stacked Bar)
			背景 在 Bokeh 初探之后,学习使用它来做个图 目标 做一个柱状图,支持多个 y 数据源,即有堆叠效果的柱状图 stacked bar 实现 单数据源 简单的柱状图 参考 Handling Cat ... 
- Wireshark网络分析就这么简单——读书笔记
			前言 什么是wireshark? wireshark可能是世界上最好的开源网络分析器,能在多个平台上(Linux.Mac和Windows)抓取和分析网络包 wireshark分析常见的协议,可以在学习 ... 
- 开源网站云查杀方案,搭建自己的云杀毒-搭建ClamAV服务器
			开源网站云查杀方案,搭建自己的云杀毒 搭建ClamAV服务器 1 前言: 在上一篇我们已经演示了整个方案,传送门<开源网站云查杀方案,搭建自己的云杀毒>:https://ww ... 
- vue中的插槽(slot)
			vue中的插槽,指的是子组件中提供给父组件使用的一个占位符,用<slot></slot>标签表示,父组件可以在这个占位符中填充任何模板代码,比如HTML.组件等,填充的内容会替 ... 
- webpack知识锦集(一)
			ebpack是一个javascript应用吃那个程序的静态模块打包器(module bundler).处理时候会递归构建一个依赖关系图,包含每个模块,将模块打包成一个或者多个bundle. 核心概念: ... 
- django models中的class meta
			Django models中的meta选项 通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样: class Foo(models.Model ... 
- flask修改flask_wtf使其支持json数据的validation验证
			flask默认是前后端不分离策略,前端通过flask+wtf表单来传递post,put...等数据. 现在前后端分离是趋势,那么对flask进行一定的修改,变为前后端分离,在前端页面中请求后端,那么请 ... 
- pyppeteer使用时常见的bug及基本使用(转)
			pyppeteer使用时常见的bug及解决办法: https://blog.csdn.net/Mr__lqy/article/details/102626025 pyppeteer的基本使用: htt ... 
- drf认证组件(介绍)、权限组件(介绍)、jwt认证、签发、jwt框架使用
			目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ... 
