Effective Java 69 Prefer concurrency utilities to wait and notify

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

时间: 2024-10-11 13:14:34

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

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 of tasks and let an executor service execute them for you, you gain great flexibility in terms of selecting appropriate execution policies. In essence,

Effective Java 目录

<Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating and Destroying Objects Consider static factory methods instead of constructors Consider a builder when faced with many constructor parameters Enforce the s

《Effective Java(中文第二版)》【PDF】下载

<Effective Java(中文第二版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382186 Java(中文第二版)>[PDF]"  TITLE="<Effective Java(中文第二版)>[PDF]" /> 编辑推荐 <Sun 公司核心技术丛书:EffectiveJava中文版(第2版)>内容全面,结构清晰,讲解详细.可作为技术人员的参考用书.编码平添乐

EFFECTIVE JAVA 第十章 并发

EFFECTIVE  JAVA  第十章  并发 66.同步访问共享的可变数据 *java语言规范保证读或写一个变量是原子的(可以保证返回的值是某个线程保存在该变量中的),除非这个变量的类型为long或double.(但并不保证一个线程写入的值对于另一个线程是可见) *synchronized修饰方法.synchronized代码块可以实现同步 *volatile修饰的变量只保证读取的是主存里最新的值而不是内存中该值的拷贝,使用volatile变量必须遵循(即变量真正独立于其他变量和自己以前的值

【电子书】Effective Java中文版下载

下载地址: 点击打开链接 (需要资源0分的联系我~) <Effective Java中文版(第2版)>主要内容:在Java编程中78条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案.通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰.健壮和高效的代码.第2版反映了Java 5中最重要的变化,并删去了过时的内容. <Effective Java中文版(第2版)>中的每条规则都以简短.独立的小文章形式出现,并

Effective Java 66 Synchronize access to shared mutable data

synchronized - Only a single thread can execute a method or block at one time. Not only does synchronization prevent a thread from observing an object in an inconsistent state, but it ensures that each thread entering a synchronized method or block s

Effective Java中文版第2版

在Java编程中78条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案.通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰.健壮和高效的代码.第2版反映了Java 5中重要的变化,并删去了过时的内容. <Effective Java中文版(第2版)>中的每条规则都以简短.独立的小文章形式出现,并通过示例代码加以进一步说明.<Effective Java中文版(第2版)>的内容包括:全新的泛型.枚举.注解.自

Effective Java 第三版——34. 使用枚举类型替代整型常量

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. Java支持两种引用类型的特殊用途的系列:一种称为枚举类型的类和一种称为注解类型的接口. 本章讨论使用这些类型系列的最佳实践. 34. 使用枚举类型替代整型常量 枚举是其合

《Effective java 中文版》(第2版)分享下载

书籍信息 书名:<Effective java 中文版>(第2版) 原作名: Effective Java Second Edition 作者: [美] Joshua Bloch 豆瓣评分:9.1分 内容简介 本书介绍了在Java编程中78条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案.通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰.健壮和高效的代码. 本书中的每条规则都以简短.独立的小文章形式出现,并通过例子