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

简介:

一、等待与通知

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此条件已经发生。








本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5408968.html,如需转载请自行联系原作者
相关文章
|
10天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
12天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
12天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
13天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
35 3
|
13天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
93 2
|
21天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
46 6
|
29天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
29天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
50 3
|
30天前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
10天前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获