Principle

Use the higher-level concurrency utilities instead of wait and notify for easiness.

Use ConcurrentHashMap in preference to Collections.synchronizedMap or Hashtable.

Use concurrent collections in preference to externally synchronized collections.

Three categories of higher-level utilities in java.util.concurrent

  1. Executor Framework (Item 68)
  2. Concurrent collections - provide high- performance concurrent implementations of standard collection interfaces such as List, Queue, and Map.   

    Since all the implementation of Concurrent collections manage their own synchronization internally it's impossible to exclude concurrent activity from a concurrent collection; locking it will have no effect but slow the program.

// Method simulates the behavior of String.intern. Concurrent canonicalizing map atop ConcurrentMap - faster!

private static final ConcurrentMap<String, String> map = new ConcurrentHashMap<String, String>();

public static String intern(String s) {

String result = map.get(s);

if (result == null) {

result = map.putIfAbsent(s, s);

if (result == null)

result = s;

}

return result;

}

Note

String.intern must use some sort of weak reference to keep from leaking memory over time.

Blocking operation - wait until they can be successfully performed.

BlockingQueue (Used for work queues) extends Queue and adds several methods, including take, which removes and returns the head element from the queue, waiting if the queue is empty.

  1. Synchronizers - Objects that enable threads to wait for one another.(eg. CountDownLatch, Semaphore, CyclicBarrier and Exchanger).   

    Countdown latches are single-use barriers that allow one or more threads to wait for one or more other threads to do something.

    /**

    * Concurrency timer demo for "69 Prefer concurrency utilities to wait and notify".

    */

    package com.effectivejava.concurrency;

    import java.util.concurrent.CountDownLatch;

    import java.util.concurrent.Executor;

    import java.util.concurrent.SynchronousQueue;

    import java.util.concurrent.ThreadPoolExecutor;

    import java.util.concurrent.TimeUnit;

    /**

    * @author Kaibo Hao

    *

    */

    public class ExecutorManager {

    // Simple framework for timing concurrent execution

    public static long time(Executor executor, int concurrency,

    final Runnable action) throws InterruptedException {

    final CountDownLatch ready = new CountDownLatch(concurrency);

    final CountDownLatch start = new CountDownLatch(1);

    final CountDownLatch done = new CountDownLatch(concurrency);

    for (int i = 0; i < concurrency; i++) {

    executor.execute(new Runnable() {

    public void run() {

    ready.countDown(); // Tell timer we're ready

    try {

    start.await(); // Wait till peers are ready

    action.run();

    } catch (InterruptedException e) {

    Thread.currentThread().interrupt();

    } finally {

    done.countDown(); // Tell timer we're done

    }

    }

    });

    }

    ready.await(); // Wait for all workers to be ready

    long startNanos = System.nanoTime();

    start.countDown(); // And they're off!

    done.await(); // Wait for all workers to finish

    return System.nanoTime() - startNanos;

    }

    /**

    * @param args

    */

    public static void main(String[] args) {

    try {

    Executor executor = new ThreadPoolExecutor(0, 2, 10,

    TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());

    long executedTime = time(executor, 2, new Runnable() {

    @Override

    public void run() {

    System.out.printf("Runing %s%n", Thread.currentThread());

    }

    });

    System.out.printf("%sns %.3fms %.3fs", executedTime,

    executedTime / 1000.0, executedTime / 1000000.0);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

Note

If a worker thread catches an InterruptedException, it reasserts the interrupt using the idiom Thread.currentThread().interrupt() and returns from its run method.

Since System.nanoTime is both more accurate and more precise, and it is not affected by adjustments to the system's real-time clock. For interval timing, always use System.nanoTime in preference to System.currentTimeMillis.

Always use the wait loop idiom to invoke the wait method; never invoke it outside of a loop.

// The standard idiom for using the wait method

synchronized (obj) {

while (<condition does not hold>)

obj.wait(); // (Releases lock, and reacquires on wakeup)

... // Perform action appropriate to condition

}

Reasons a thread might wake up when the condition does not hold:

• Another thread could have obtained the lock and changed the guarded state between the time a thread invoked notify and the time the waiting thread woke.

• Another thread could have invoked notify accidentally or maliciously when the condition did not hold. Classes expose themselves to this sort of mischief by waiting on publicly accessible objects. Any wait contained in a synchronized method of a publicly accessible object is susceptible to this problem.

• The notifying thread could be overly "generous" in waking waiting threads. For example, the notifying thread might invoke notifyAll even if only some of the waiting threads have their condition satisfied.

• The waiting thread could (rarely) wake up in the absence of a notify. This is known as a spurious wakeup[Posix, 11.4.3.6.1; JavaSE6].

Summary

using wait and notify directly is like programming in "concurrency assembly language," as compared to the higher-level language provided by java.util.concurrent. There is seldom, if ever, a reason to use wait and notify in new code. If you maintain code that uses wait and notify, make sure that it always invokes wait from within a while loop using the standard idiom. The notifyAll method should generally be used in preference to notify. If notify is used, great care must be taken to ensure liveness.

Effective Java 69 Prefer concurrency utilities to wait and notify的更多相关文章

  1. Effective Java 35 Prefer annotations to naming patterns

    Disadvantages of naming patterns Typographical errors may result in silent failures. There is no way ...

  2. Effective Java 53 Prefer interfaces to reflection

    Disadvantage of reflection You lose all the benefits of compile-time type checking, including except ...

  3. Effective Java 68 Prefer executors and tasks to threads

    Principle The general mechanism for executing tasks is the executor service. If you think in terms o ...

  4. Effective Java 18 Prefer interfaces to abstract classes

    Feature Interface Abstract class Defining a type that permits multiple implementations Y Y Permitted ...

  5. Effective Java 20 Prefer class hierarchies to tagged classes

    Disadvantage of tagged classes 1. Verbose (each instance has unnecessary irrelevant fields). 2. Erro ...

  6. Effective Java 25 Prefer lists to arrays

    Difference Arrays Lists 1 Covariant Invariant 2 Reified at runtime Erased at run time 3 Runtime type ...

  7. Effective Java 46 Prefer for-each loops to traditional for loops

    Prior to release 1.5, this was the preferred idiom for iterating over a collection: // No longer the ...

  8. Effective Java 49 Prefer primitive types to boxed primitives

    No. Primitives Boxed Primitives 1 Have their own values Have identities distinct from their values 2 ...

  9. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

随机推荐

  1. 直接拿来用!最火的Android开源项目

    GitHub在中国的火爆程度无需多言,越来越多的开源项目迁移到GitHub平台上.更何况,基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要.利用这些项目,有时能够让你 ...

  2. linux内核分析课程笔记(二)

    运行一个精简的操作系统内核 存储程序计算机是几乎所有计算机的基础逻辑框架. 堆栈是计算机中非常基础的东西,在最早计算机没有高级语言时,在高级语言出现之前,我们没有函数的概念.但高级语言出现后有了函数调 ...

  3. 高级四则运算器—结对项目总结(193 &105)

    高级四则运算器—结对项目总结 为了将感想与项目经验体会分割一下,特在此新开一篇博文. 界面设计 啥都不说,先上图震慑一下... 上面的三个界面是我们本次结对项目的主界面,恩,我也觉得挺漂亮的!你问我界 ...

  4. ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践

    解决跨域调用服务并设置headers 主要的解决方法需要通过服务器端设置响应头.正确响应options请求,正确设置 JavaScript端需要设置的headers信息 方能实现. 此处手札 供后人参 ...

  5. 三种对话框的示例(alert,confirm,prompt)

    示例代码 <h2>JavaScriptDialog</h2> <hr/> <buttononclick="btn_alert()"> ...

  6. 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架开发随笔一

    公司业务量比较大,接了很多项目,为了缩短开发周期老板让我牵头搭建了一个敏捷开发框架. 我们主要的业务是做OA.CRM.ERP一类的管理系统,一个通用的后台搭出来,再配合一些快速开发的组件开发效率能提高 ...

  7. SqlServer常用语句参考

    1.SQL SERVER中如何使用SQL 语句复制表结构: select * into 新表 from 旧表 where 1=2 把“旧表”的表结构复制到“新表”,1=2不复制数据,如果要复制数据,就 ...

  8. PHP框架Swoole的一个定时器Timer特性

    在各种业务型系统中,往往需要服务器在后台扫描相关数据,触发相应的统计.通知等操作. 比如对于一个项目管理系统,需要每天的特定时间内,统计每项任务的执行.到期情况.整个项目的进度等等,根据统计情况,做相 ...

  9. 我见过的几门语言中的hello world

    1.Java public class hello { public static void main(String[] args){ System.out.println("hello w ...

  10. ahjesus mongodb指定到数据盘连接不上的解决方案

    关于配置路径指定到数据盘会出现连接不上的情况 我发现是因为数据盘权限不足引起的,目前没找到治本的方法 有个治标的方法就是设置数据盘的权限和用户 sudo chmod 777 * -R  /path/d ...