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. 什么是https?

    很久之前注意到了https这个新出来的协议,当时感觉到只是一个加密的协议,然后没有什么关注,只知道他和http的区别就在于加密,最近突然很多人问起了这个https到底是什么?于是上网查了查资料,总结之 ...

  2. 虚拟机service network restart没有反应解决方法

      一般我们新copy的虚拟机或新克隆的虚拟机第一次启动时都会出现没有ip地址的情况: [root@zejin243 network-scripts]# ifconfig lo        Link ...

  3. jquery1.9+获取append后的动态元素

    jquery 1.9+放弃了live,说是用on代替了! 那么如果我们以前用live来获取jquery动态添加的元素,现在应该用on怎么写呢? 首先: <div id="one&quo ...

  4. 字符串与json之间的相互转化

    先在数据库中建表: 再从后台将表取出来,然后转化为json格式,再将其执行ToString()操作后,赋值给前台的隐藏域. 注意引用using Newtonsoft.Json; 前台利用js将隐藏域中 ...

  5. AxWebBrowser与WebBrowserU盾登陆时的使用

    PS:上个月为财务小妹做了个自动上传报表的工具,财务妹子表示调戏我很开心T_T~~.   由于该小程序涉及到登陆,准备用WebBroswer,这一下撞墙上了,无法展示U盾密码框.   我在博问上的问题 ...

  6. 【jQuery基础学习】04 jQuery中的表格操作及cookie插件的使用

    这章本来准备写成jQuery的表单操作和表格操作的. 然而昨天吧jQuery的表单操作看完,发现全部在炒之前章节的剩饭,所以就没写出来. 那么今天就来看看表格吧. 因为平常做的都是公司的内部管理系统, ...

  7. jquery 全选 全不选 反选

    1.概述 在项目中经常遇到列表中对复选框进行勾选操作,全选...反选.. 2. example <html> <body> <form id="test-for ...

  8. ahjesus让nodejs支持dotjs模板

    经过几天的实验加搜索,终于知道一个中间件可以解决这个问题了 npm install consolidate consolidate传送门 传送门2使用说明传送门快照:ahjesus Since doT ...

  9. 西邮Linux兴趣小组2016免试题

    4.28的宣讲会圆满结束(就在写这段话之前不久),对于西邮Linux兴趣小组这一次纳新,身为局外人表示:还是有历史,还是会玩,还是厉害哈. 华丽的分割线里面是自己之前的攻关战略,最后补充了宣讲会上学长 ...

  10. apple store链接格式文档

    备份一下: The app on Appstore has specific URL format http://itunes.apple.com/[country-code]/app/[app-na ...