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 学习笔记之如何实现简单相机功能

    PS:看来算法和数据结构还是非常有用的,以后每天都练习两道算法题目...这次忘了对代码进行折叠了..导致篇幅过长... 学习内容: 1.Android如何实现相机功能... 2.如何实现音频的录制.. ...

  2. 【第三课】ANR和OOM——贪快和贪多的后果(上)

    恼人的ANR 早先年用Android的时候,就连很多知名的app也总是莫名其妙崩溃,好像手机快的时候会崩溃,手机卡的时候app会卡死.卡死的时候会弹出来一个框,询问是要结束app还是继续等待.这就是A ...

  3. 重构第19天 提取工厂类(Extract Factory Class)

    理解:本文中的“提取工厂类”是指如果要创建的对象很多,则代码会变的很复杂.一种很好的方法就是提取工厂类. 详解:一般来说我们需要在代码中设置一些对象,以便获得它们的状态,从而使用对象,所谓的设置通常来 ...

  4. ASP.NET后台执行JS代码

    1. 用Response.Write方法 代码如下:Response.Write("<script type='text/javascript'>alert("XXX& ...

  5. 怎样在C#中从数据库中读取数据(数据读取器)

    实现在C#中通过语句,查询数据库中的数据 SqlConnection con = null; //创建SqlConnection 的对象 try    //try里面放可能出现错误的代码        ...

  6. sencha combobox下拉框不用jsonstore,直接使用字符串数组做数据源

    combobox下拉框的store除了可以选择一个jsonstore来加载数据,还可以直接使用符串Array做数据源. { xtype: 'combobox', fieldLabel: 'Label' ...

  7. 与众不同 windows phone (35) - 8.0 新的启动器: ShareMediaTask, SaveAppointmentTask, MapsTask, MapsDirectionsTask, MapDownloaderTask

    [源码下载] 与众不同 windows phone (35) - 8.0 新的启动器: ShareMediaTask, SaveAppointmentTask, MapsTask, MapsDirec ...

  8. mysql select语句解析

    select语句用于从一个或多个数据表选出特定行.特定列的交集 最简单的select语句的语法格式如下: select column1,column2 ........      (列) from 数 ...

  9. Linux守护进程的编程实现(转)

    http://blog.csdn.net/zg_hover/article/details/2553321 http://blog.csdn.net/kongdefei5000/article/det ...

  10. 伏羲八卦、文王六十四卦、老子阴阳太极、西方哲学辩证与"解耦和复用”思想的异曲同工之妙

    伏羲八卦.文王六十四卦.老子阴阳太极.西方哲学辩证与"解耦和复用”思想的异曲同工之妙     问题:任何程序语言在遇到复杂逻辑时,代码维护难度就会加大,如何处理该问题? 答案:重构,模块化. ...