三个不同的线程将会共用一个 Foo 实例,它们会被异步启动。
线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。
输入: [1,2,3]
输出: "onetwothree"
解释:
有三个线程会被异步启动。
输入 [1,2,3] 表示线程 A 将会调用 one() 方法,线程 B 将会调用 two() 方法,线程 C 将会调用 three() 方法。
正确的输出是 "onetwothree"。
排序的思路就是 线程 C 等待线程 B 执行完毕,线程 B 等待线程 A 执行完毕,通过线程阻塞的方式实现,JUC 提供了许多的多线程工具类。
- 解法一:CountDownLoatch
/**
* 通过 CountDownLatch
*/
public static class Foo1 {
private CountDownLatch countDownLatchSecond = new CountDownLatch(1);
private CountDownLatch countDownLatchThird = new CountDownLatch(1);
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
countDownLatchSecond.countDown();
}
public void second(Runnable printSecond) throws InterruptedException {
countDownLatchSecond.await();
printSecond.run();
countDownLatchThird.countDown();
}
public void third(Runnable printThird) throws InterruptedException {
countDownLatchThird.await();
printThird.run();
}
}
- 解法二:Object 内置锁
/**
* 通过 Object 内置锁
*/
public static class Foo2 {
private final Object lock = new Object();
private int state = 1;
public void first(Runnable printFirst) throws InterruptedException {
synchronized (lock) {
printFirst.run();
state = 2;
lock.notifyAll();
}
}
public void second(Runnable printSecond) throws InterruptedException {
synchronized (lock) {
while (state != 2) {
lock.wait();
}
printSecond.run();
state = 3;
lock.notifyAll();
}
}
public void third(Runnable printThird) throws InterruptedException {
synchronized (lock) {
while (state != 3) {
lock.wait();
}
printThird.run();
}
}
}
- 解法三:Lock 和 Condition
/**
* 通过 Lock 和 Condition
*/
public static class Foo3 {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private int state = 1;
public void first(Runnable printFirst) throws InterruptedException {
lock.lock();
try {
printFirst.run();
state = 2;
condition.signalAll();
} finally {
lock.unlock();
}
}
public void second(Runnable printSecond) throws InterruptedException {
lock.lock();
try {
while (state != 2) {
condition.await();
}
printSecond.run();
state = 3;
condition.signalAll();
} finally {
lock.unlock();
}
}
public void third(Runnable printThird) throws InterruptedException {
lock.lock();
try {
while (state != 3) {
condition.await();
}
printThird.run();
} finally {
lock.unlock();
}
}
}
- 解法四:Semaphore
/**
* 通过 Semaphore
*/
public static class Foo4 {
private Semaphore semaphoreSecond = new Semaphore(0);
private Semaphore semaphoreThird = new Semaphore(0);
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
semaphoreSecond.release();
}
public void second(Runnable printSecond) throws InterruptedException {
semaphoreSecond.acquire();
printSecond.run();
semaphoreThird.release();
}
public void third(Runnable printThird) throws InterruptedException {
semaphoreThird.acquire();
printThird.run();
}
}
20 Google Search Tips to Use Google More Efficiently 用好谷歌搜索的 20 条技巧
- 使用 Tab 分类,比如图片、新闻、视频等
- 使用双引号,精确匹配关键词,比如: “浪潮之巅 吴军”
- 使用连字符
-
排除词语,比如:见识 -吴军 - 使用冒号
site:url
搜索指定网站,比如:吴军 site:dangdang.com - 查找链接到另一个页面的页面
link:url
,比如:link:qq.com - 使用星号
*
通配符,比如:生活不止 * 苟且 - 查找与其他网站相似的网站
related:url
,比如:related:amazon.com - 用谷歌搜索做数学,比如:8 * 5 + 5
- 一个搜索多个关键词
OR
,比如:巧克力 OR 白巧克力 - 搜索一系列数字
..
,比如:41..43 - 保持简单,比如:附近的披萨店
- 逐渐添加搜索词,比如:
- 首先尝试:工作面试
- 其次尝试:准备工作面试
- 再次尝试:如何准备工作面试
- 使用网站会用的词汇,比如:“我头疼”可以换成“头痛缓解”
- 只用重要的词汇,比如:
- 不要用:我从哪儿可以找到提供配送的餐馆?
- 而要用:附近的餐馆
- 谷歌搜索有快捷方式,就像上面的计算器一样。比如:北京时间、杭州天气
- 拼写不那么重要,谷歌搜索会帮你纠正语法和词汇。
- 使用描述性词语,比如:如何安装 Ubuntu 的驱动?
- 查找特定文件
filetype:pdf
,比如:文明之光 filetype:pdf - 货币和单位换算,
- 追踪你的包裹
谷歌搜索是最棒的搜索工具,比某度好一万倍,善用谷歌是一种高效的方式。
推荐一个静态博客写作客户端 Gridea,使用它可以方便地管理文章,进行分类、打标签等,一键同步到 GitHub,提供了多套主题,支持配置域名和评论功能,Windows、Mac 、Linux 全平台支持。我的博客托管在 GitHub 上,以前使用 Hexo 发布,但是没有本地管理功能,想修改文章非常麻烦。现在用 Gridea 发布,果然优雅了不少啊。
程序员一般不喜欢写文档,遇到问题时又骂别人不写文档。在我看来,文档和代码一样重要,开源库的 API 文档写得清晰明了,开发者使用时也省心。最怕的是,过了一段时间,自己的代码都捋不清了。所以,尽可能多些文档吧,为了自己也为了接盘侠 :)