一、等待与通知

public final void wait() throws InterruptedException

     等待条件的发生。

public final void wait(long timeout) throws InterruptedException

     等待条件的发生。假设通知没有在timeout指定的时间内发生,它还是会返回。
public final void wait(long timeout, int nanos) throws InterruptedException
     等待条件的发生。

假设通知没有在timeout指定的毫秒与纳秒内发生。它还是会返回。


public final void notify()

     通知正在等待的Thread此条件已经发生。

public final void notifyAll()
     通知全部正在等待的Thread此条件已经发生。

    等待-通知机制的目的为何?它是怎样运作的? 
     等待-通知机制是同步机制。它更是一个通信机制:它可以让某个Thread与其它Thread在特定条件符合时进行通信。等待-通知机制并没有指定特定条件是什么。
    等待-通知机制可以用来代替synchronized机制吗?
     不行。wait、notify、notifyAll方法方法必须从synchronized方法块中调用,由于须要其确保等待与通知的线程安全不会出现竞态条件。

public class AnimatedCharacterDisplayCanvas extends CharacterDisplayCanvas implements CharacterListener, Runnable {

    private boolean done = true;
private int curX = 0;
private Thread timer = null; public AnimatedCharacterDisplayCanvas() {
} public AnimatedCharacterDisplayCanvas(CharacterSource cs) {
super(cs);
} public synchronized void newCharacter(CharacterEvent ce) {
curX = 0;
tmpChar[0] = (char) ce.character;
repaint();
} protected synchronized void paintComponent(Graphics gc) {
Dimension d = getSize();
gc.clearRect(0, 0, d.width, d.height);
if (tmpChar[0] == 0)
return;
int charWidth = fm.charWidth(tmpChar[0]);
gc.drawChars(tmpChar, 0, 1,
curX++, fontHeight);
} public synchronized void run() {
while (true) {
try {
if (done) {
wait();
} else {
repaint();
wait(100);
}
} catch (InterruptedException ie) {
return;
}
}
} public synchronized void setDone(boolean b) {
done = b; if (timer == null) {
timer = new Thread(this);
timer.start();
}
if (!done)
notify();
}
}

     sleep与wait方法的差别?
     wait与notify方法都必须在同步方法中。在一个类中的两个同步方法使用的都是当前this作为锁,wait方法运行后会释放掉当前方法锁。由于假设不释放的话notify永远无法获取到此锁,也就永远无法运行notify。
     sleep方法是不会释放锁的,而且堵塞当前线程,一直到sleep指定的时间结束。

等待-通知机制与同步
存在于等待-通知机制中的竞态条件细节是什么?
1. 第一个Thread測试条件并确认它须要等待
2. 第二个Thread设定此条件
3. 第二个Thread调用notify方法,这不会被收到。由于第二个Thread还没有进入等待
4. 第一个Thread调用wait方法

这个潜在的竞态条件状况是怎样解决的? 
     调用wait与调用notify的方法都使用同一锁(当前对象this)。由锁来保证操作的原子性。

假设Thread收到通知,是否可以保证条件被正确的设定?
     不是。描写叙述情景

wait(), notify() 与 notifyAll()
当一个以上的Thread在等待通知时哪个Thread会在调用notify的时候收到通知?
     Java规范未定义哪一个Thread收到通知。

可是Object class 提供另外一个方法notifyAll


是否noitfyAll方法真的唤醒全部的Thread?
     是也不是。

全部等待中Thread都会被唤醒,但它们都还没要又一次取得对象的lock。所以这些Thread并非并行地运行:它们都必须等待对象lock被释放掉。

因此,一次仅仅有一个Thread可以运行,且仅仅有在调用notifyAll方法的这个Thread释放掉它的lock之后。


为什么要唤醒全部的Thread?
     1. 有多个Thread处于等待状态,无法指定哪一个收到通知
     2. 并不知道详细有多少个Thread处于等待,干脆同步通知。由等待中的Thread自己处理。

等待-通知机制与synchronized块
public class AnimatedCharacterDisplayCanvas extends CharacterDisplayCanvas implements CharacterListener, Runnable {

    private boolean done = true;
private int curX = 0;
private Thread timer = null;
private Object doneLock = new Object(); public AnimatedCharacterDisplayCanvas() {
} public AnimatedCharacterDisplayCanvas(CharacterSource cs) {
super(cs);
} public synchronized void newCharacter(CharacterEvent ce) {
curX = 0;
tmpChar[0] = (char) ce.character;
repaint();
} protected synchronized void paintComponent(Graphics gc) {
Dimension d = getSize();
gc.clearRect(0, 0, d.width, d.height);
if (tmpChar[0] == 0)
return;
int charWidth = fm.charWidth(tmpChar[0]);
gc.drawChars(tmpChar, 0, 1,
curX++, fontHeight);
} public void run() {
synchronized(doneLock) {
while (true) {
try {
if (done) {
doneLock.wait();
} else {
repaint();
doneLock.wait(100);
}
} catch (InterruptedException ie) {
return;
}
}
}
} public void setDone(boolean b) {
synchronized(doneLock) {
done = b; if (timer == null) {
timer = new Thread(this);
timer.start();
}
if (!done)
doneLock.notify();
}
}
}

二、条件变量

POSIX条件变量的四个基本函数:wait(), thimeed_wait(), signal, broadcast。直接相应Java提供的wait(), wait(long),notify(),notifyAll

     J2SE 5.0增加提供条件变量功能的类。

此类食欲Lock interface并用。由于这个新的interface是与调用以及lock对象分开的,它在用法上的灵活性就如筒其它Threading系统中的条件变量一样。

public class RandomCharacterGenerator extends Thread implements CharacterSource {
private static char[] chars;
private static String charArray = "abcdefghijklmnopqrstuvwxyz0123456789";
static {
chars = charArray.toCharArray();
} private Random random;
private CharacterEventHandler handler;
private boolean done = true;
private Lock lock = new ReentrantLock();
private Condition cv = lock.newCondition(); public RandomCharacterGenerator() {
random = new Random();
handler = new CharacterEventHandler();
} public int getPauseTime() {
return (int) (Math.max(1000, 5000 * random.nextDouble()));
} public void addCharacterListener(CharacterListener cl) {
handler.addCharacterListener(cl);
} public void removeCharacterListener(CharacterListener cl) {
handler.removeCharacterListener(cl);
} public void nextCharacter() {
handler.fireNewCharacter(this,
(int) chars[random.nextInt(chars.length)]);
} public void run() {
try {
lock.lock();
while (true) {
try {
if (done) {
cv.await();
} else {
nextCharacter();
cv.await(getPauseTime(), TimeUnit.MILLISECONDS);
}
} catch (InterruptedException ie) {
return;
}
}
} finally {
lock.unlock();
}
} public void setDone(boolean b) {
try {
lock.lock();
done = b; if (!done) cv.signal();
} finally {
lock.unlock();
}
}
}
     为什么使用Condition而不使用wait与notify?或者说是二者的差别?
     1. Condition与wait同样都是由于须要确保同步安全(即避免竞态条件)而必须使用锁机制保证。

     2. Lock对象不能与wait、notify方法搭配。由于这些方法已经在内部被用来实现Lock对象,持有lock对象并不表示持有了该对象的同步锁。
     3. Condition对象不像等待-通知机制,它是被创建不同的对象。

对每个Lock对象都能够创建一个以上的Condition对象。这表示我们能够针对个别的Thread或ThreadGroup进行独立的设定。



Condition方法:
void await()
     等待条件的发生。

void awaitUniterruptibly()
     等待条件的发生。

与await()不同,它的调用不可能被中断。

void signal()
     通知某个等待使用Condition对象的Thread此条件已经发生。
void signalAll()
     通知全部等待使用Condition对象的Thread此条件已经发生。






Java 线程第三版 第四章 Thread Notification 读书笔记的更多相关文章

  1. Java 线程第三版 第五章 极简同步技巧 读书笔记

    一.能避免同步吗? 取得锁会由于下面原因导致成本非常高:     取得由竞争的锁须要在虚拟机的层面上执行很多其它的程序代码.     要取得有竞争锁的线程总是必须等到锁被释放后. 1. 寄存器的效应 ...

  2. 《Java并发编程实战》第六章 任务运行 读书笔记

    一. 在线程中运行任务 无限制创建线程的不足 .线程生命周期的开销很高 .资源消耗 .稳定性 二.Executor框架 Executor基于生产者-消费者模式.提交任务的操作相当于生产者.运行任务的线 ...

  3. 《Java并发编程实战》第五章 同步容器类 读书笔记

    一.同步容器类 1. 同步容器类的问题 线程容器类都是线程安全的.可是当在其上进行符合操作则须要而外加锁保护其安全性. 常见符合操作包括: . 迭代 . 跳转(依据指定顺序找到当前元素的下一个元素) ...

  4. Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记

    第一章 Thread导论 为何要用Thread ? 非堵塞I/O      I/O多路技术      轮询(polling)      信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...

  5. Java 线程第三版 第九章 Thread调度 读书笔记

    一.Thread调度的概述 import java.util.*; import java.text.*; public class Task implements Runnable { long n ...

  6. Java 线程第三版 第八章 Thread与Collection Class 读书笔记

        JDK1.2引入最有争议性的改变是将集合类默觉得不是Thread安全性的. 一.Collection Class的概述 1. 具有Threadsafe 的Collection Class: j ...

  7. Java核心技术卷一基础知识-第7章-图形程序设计-读书笔记

    第7章 图形程序设计 本章内容: * Swing概述 * 创建框架 * 框架定位 * 在组件中显示信息 * 处理2D图形 * 使用颜色 * 文本使用特殊字体 * 显示图像 本章主要讲述如何编写定义屏幕 ...

  8. 《Java并发编程实战》第十三章 显示锁 读书笔记

    一.Lock与 ReentrantLock Lock 提供一种无条件的.可轮询的.定时的.可中断的锁获取操作,全部加锁和解锁的方法都是显式的. public interface Lock { void ...

  9. Javascript模式(第四章函数)------读书笔记

    一 背景 js函数的两个特点:1 函数是第一类对象(first-class object):2 函数可以提供作用域 1 函数是对象: 1 函数可以在运行时动态创建,还可以在程序执行过程中创建 2 可以 ...

随机推荐

  1. plsql免安装客户端的配置

    不安装oracle,在安装了plsql之后,需要连接数据库,连接数据库需要在tns中tnsnames.ora中配置 首先需要两个文件: network instantclient-basic-win3 ...

  2. RabbitMq简单应用

    服务端: <?php //配置信息 $conn_args = array( 'host' => '127.0.0.1', 'port' => '5672', 'login' => ...

  3. [转]避免头文件重复包含以及#ifndef 与 #program once 的区别

    为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式.在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一 ...

  4. Windows修改默认远程端口号3389

    1.打开注册表:运行-regedit: 2.HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\Wds\Repwd\ ...

  5. MySQL的Auto-Failover功能

    今天来体验一下MySQL的Auto-Failover功能,这里用到一个工具MySQL Utilities,它的功能很强大.此工具提供如下功能:(1)管理工具 (克隆.复制.比较.差异.导出.导入)(2 ...

  6. 关于USBHID协议以及鼠标键盘描述符的解释【转】

    转自:https://blog.csdn.net/jiujiujiuqiuqiuqiu/article/details/47277685 一.HID设备识别 前面有提到关于SCSI协议的USB设备实现 ...

  7. Bogus URL svn: is not properly URI-encoded

    问题描述: 从浏览器地址栏复制出来的url   放到eclipse 的svn插件里,新建资源库位置 总是报错 Bogus URL svn: **********************  is not ...

  8. 关于sudo 权限被修改的解决方法

    在用sudo安装文件的时候,出现如下错误提示: sudo: /etc/sudoers is world writable sudo: no valid sudoers sources found, q ...

  9. spring-service.xml 模板

    ssm模板 <?xml version="1.0" encoding="UTF-8"?>  <beans xmlns="http:/ ...

  10. linux进程的一些日常处理

    linux 下查看一个进程运行路径的方法 在linux下查看进程大家都会想到用 ps -ef|grep XXX 可是看到的不是全路径,怎么看全路径呢? 每个进程启动之后在 /proc下面有一个于pid ...