Java 线程第三版 第四章 Thread Notification 读书笔记

时间:2023-02-26 17:11:18

一、等待与通知

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. Java -- 获取当前日期、当月月初日期、月末日期

    Learn From:http://blog.csdn.net/sunhuwh/article/details/39161323 public class CalendarTest { public ...

  2. [Algorithms(Princeton)] Week1 - Percolation

    public class Percolation { private boolean[] openSites; private int gridN; private WeightedQuickUnio ...

  3. lintcode 中等题: reverse linked list II 翻转链表II

    题目 翻转链表 II 翻转链表中第m个节点到第n个节点的部分 样例 给出链表1->2->3->4->5->null, m = 2 和n = 4,返回1->4-&gt ...

  4. java基本对象Integer,String比较相等及equal案例说明

    Integer i = new Integer(100); Integer i2 = new Integer(100); if(i == i2){ System.out.println("A ...

  5. JavaScript忍者秘籍——原型

    概要:本篇博客主要介绍JavaScript的原型 1.对象实例化 - 初始化的优先级 初始化操作的优先级如下: ● 通过原型给对象实例添加的属性 ● 在构造器函数内给对象实例添加的属性 在构造器内的绑 ...

  6. Mermaid js与流程图、甘特图..

    https://mermaidjs.github.io/gantt.html https://github.com/jdbranham/grafana-diagram 用 mermaid 画甘特图 h ...

  7. andorid 直接解压后的xml的解密

    1.首先可以去看看这个gitHub: https://github.com/tracer0tong/axmlprinter 2.把apk.py 和 axmlprinter.py下载下来. 2.1(如果 ...

  8. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  9. jsp脚本语法

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  10. &lbrack;linux基础学习&rsqb;默认的目录介绍

    以下用一个表格来罗列linux默认的目录或文件及其用途: 目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - / ...