按序打印

解法一:使用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. 大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)

    大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)   现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一 ...

  2. 什么是Activiti

    什么是Activiti Activiti属于工作流引擎的一个开源实现.Activiti由Tom Bayen发起.在2010年5月发布了第一个版本.命名也很有意思的采取了Activities(活动)的化 ...

  3. 使用veloticy-ui生成文字动画

    前言 最近要实现一个类似文字波浪线的效果,使用了velocity-ui这个动画库,第一个感觉就是使用简单,代码量少,性能优异,在此简单介绍一下使用方法,并实现一个看上去不错的动画.具体使用方法可以点击 ...

  4. 3DGIS+BIM集成与智慧城市应用

    ZTMap3D是基于网络的三维地理信息系统平台软件,利用 ZTMap3D能够实现三维地理信息和虚拟现实,是数字化地球和数字化城市建设的基础平台. BIM(building information mo ...

  5. DBProxy快速入门

    1. DBProxy安装 1.1 安装依赖项 CentOS yum install -y Percona-Server-devel-55.x86_64 Percona-Server-client-55 ...

  6. session、cookie和taken的区别

    http是无状态的协议,所以要维持应用的会话形式,就需要加入以下几种机制,来进行会话跟踪,识别用户身份(当同一用户进行多次操作,不用反复请求建立新的连接,从而节省服务器资源和处理速度)   生成位置 ...

  7. CentOS7采用tar.gz包方式安装Mysql5.7

    软件:VMware Linux版本:CentOS 7 一.安装mysql(采用tar.gz包安装Mysql5.7) 1.安装开发工具包 [root@localhost ~]# yum groups m ...

  8. 手写 Promise 符合 Promise/A+规范

    异步编程是前端开发者必需的技能,过去管理异步的主要机制都是通过函数回调,然而会出现像“回调地狱”这样的问题.为了更好的管理回调,ES6 增加了一个新的特性 Promise.Promise 是 ES7 ...

  9. 实用干货丨如何使用Prometheus配置自定义告警规则

    前 言 Prometheus是一个用于监控和告警的开源系统.一开始由Soundcloud开发,后来在2016年,它迁移到CNCF并且称为Kubernetes之后最流行的项目之一.从整个Linux服务器 ...

  10. XSS-Labs(Level1-10)

    Level-1 简单尝试 使用基础poc<script>alert(1)</script> 代码审计 <?php ini_set("display_errors ...