按序打印

解法一:使用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并发题解的更多相关文章

  1. LeetCode OJ 题解

    博客搬至blog.csgrandeur.com,cnblogs不再更新. 新的题解会更新在新博客:http://blog.csgrandeur.com/2014/01/15/LeetCode-OJ-S ...

  2. Leetcode 简略题解 - 共567题

    Leetcode 简略题解 - 共567题     写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ...

  3. LeetCode 算法题解 js 版 (001 Two Sum)

    LeetCode 算法题解 js 版 (001 Two Sum) 两数之和 https://leetcode.com/problems/two-sum/submissions/ https://lee ...

  4. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  5. LeetCode一句话题解

    深度优先搜索 人生经验 1. 需要输出所有解.并由于元素集有重复元素,要求返回的结果需要去重的情况,可考虑使用值对应数量的map,然后分别考虑依次取不同数量该值的可能. LeetCode39 题目:给 ...

  6. [leetcode] 位操作题解

    子集 题目[78]:给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 示例: 输入: nums = [1,2,3] 输出: [ [3],   [1],   [2],   [ ...

  7. LeetCode 中等题解(3)

    34 在排序数组中查找元素的第一个和最后一个位置 Question 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂 ...

  8. LeetCode 中等题解(1)

    16 最接近的三数之和 Question 给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 nums 中的三个整数,使得它们的和与 target 最接近.返回这三个数的和. ...

  9. leetcode个人题解——two sum

    这是leetcode第一题,通过较为简单. 第一题用来测试的,用的c,直接暴力法过, /** * Note: The returned array must be malloced, assume c ...

随机推荐

  1. C# 关于位运算的学习笔记

    一.理解什么是位运算 程序中的所有内容在计算机内存中都是以二进制的形式储存的(即:0或1),简单来说位运算就是直接对在内存中的二进制数的每位进行运算操作. 二.学习前先了解一下有哪些运算,运算符都怎么 ...

  2. 提取.bank音频包。 Extract .bank audio files

    转载请注明出处! 首先我们需要提取的文件是 .bank 的音频文件包,里面包含很条音频. 这是我们会用到工具 step1: 运行  quickbms.exe, 它会自动打开选择文件窗口,我们直接选择下 ...

  3. blender 2.8 [学习笔记-04] 编辑模式-网格拆分

    在编辑模式下

  4. 微信小程序结构目录、配置介绍、视图层(数据绑定,运算,列表渲染,条件渲染)

    目录 一.小程序结构目录 1.1 小程序文件结构和传统web对比 1.2 基本的项目目录 二.配置介绍 2.1 配置介绍 2.2 全局配置app.json 2.3 page.json 三.视图层 3. ...

  5. HashSet底层、及存入对象时候如何保持唯一

    HashSet底层.及存入对象时候如何保持唯一 在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里. 但是当位于一个桶中的元素较多,即hash ...

  6. idea创建django项目

    1.环境.版本 os:windows10 ide:idea python:2.7 django:1.11.25 其他的python.django不确定这么弄会不会有其他问题. 2.python 官网下 ...

  7. Python3 面向对象之:单继承

    一:什么面向对象的继承? 比较官方的说法就是: 继承(英语:inheritance)是面向对象软件技术当中的一个概念.如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A ...

  8. 华为面试题(JAVA版)

    [编程题] 扑克牌大小时间限制:10秒空间限制:131072K扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A,2各4张,小王1张,大王1张.牌面从小到大用如下字符和字符串表示(其中,小写 ...

  9. 0919-The Standard of Code Review

    The primary purpose of code review is to make sure that the overall code health of Google’s code bas ...

  10. C#中无边框窗体拖动

    //定义一个bool变量标识是否拖动窗体 private bool isMove = false; //记录鼠标的位置 private Point point; 定义的变量 /// <summa ...