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,如需转载请自行联系原作者
相关文章
|
1天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
8 0
|
5天前
|
安全 Java
深入理解 Java 多线程和并发工具类
【4月更文挑战第19天】本文探讨了Java多线程和并发工具类在实现高性能应用程序中的关键作用。通过继承`Thread`或实现`Runnable`创建线程,利用`Executors`管理线程池,以及使用`Semaphore`、`CountDownLatch`和`CyclicBarrier`进行线程同步。保证线程安全、实现线程协作和性能调优(如设置线程池大小、避免不必要同步)是重要环节。理解并恰当运用这些工具能提升程序效率和可靠性。
|
5天前
|
安全 Java
java多线程(一)(火车售票)
java多线程(一)(火车售票)
|
6天前
|
安全 Java 调度
Java并发编程:深入理解线程与锁
【4月更文挑战第18天】本文探讨了Java中的线程和锁机制,包括线程的创建(通过Thread类、Runnable接口或Callable/Future)及其生命周期。Java提供多种锁机制,如`synchronized`关键字、ReentrantLock和ReadWriteLock,以确保并发访问共享资源的安全。此外,文章还介绍了高级并发工具,如Semaphore(控制并发线程数)、CountDownLatch(线程间等待)和CyclicBarrier(同步多个线程)。掌握这些知识对于编写高效、正确的并发程序至关重要。
|
6天前
|
安全 Java 程序员
Java中的多线程并发编程实践
【4月更文挑战第18天】在现代软件开发中,为了提高程序性能和响应速度,经常需要利用多线程技术来实现并发执行。本文将深入探讨Java语言中的多线程机制,包括线程的创建、启动、同步以及线程池的使用等关键技术点。我们将通过具体代码实例,分析多线程编程的优势与挑战,并提出一系列优化策略来确保多线程环境下的程序稳定性和性能。
|
6天前
|
缓存 分布式计算 监控
Java并发编程:深入理解线程池
【4月更文挑战第17天】在Java并发编程中,线程池是一种非常重要的技术,它可以有效地管理和控制线程的执行,提高系统的性能和稳定性。本文将深入探讨Java线程池的工作原理,使用方法以及在实际开发中的应用场景,帮助读者更好地理解和使用Java线程池。
|
7天前
|
存储 安全 Java
Java中的容器,线程安全和线程不安全
Java中的容器,线程安全和线程不安全
15 1
|
7天前
|
Java 开发者
Java中多线程并发控制的实现与优化
【4月更文挑战第17天】 在现代软件开发中,多线程编程已成为提升应用性能和响应能力的关键手段。特别是在Java语言中,由于其平台无关性和强大的运行时环境,多线程技术的应用尤为广泛。本文将深入探讨Java多线程的并发控制机制,包括基本的同步方法、死锁问题以及高级并发工具如java.util.concurrent包的使用。通过分析多线程环境下的竞态条件、资源争夺和线程协调问题,我们提出了一系列实现和优化策略,旨在帮助开发者构建更加健壮、高效的多线程应用。
7 0
|
8天前
|
缓存 监控 Java
Java并发编程:线程池与任务调度
【4月更文挑战第16天】Java并发编程中,线程池和任务调度是核心概念,能提升系统性能和响应速度。线程池通过重用线程减少创建销毁开销,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。任务调度允许立即或延迟执行任务,具有灵活性。最佳实践包括合理配置线程池大小、避免过度使用线程、及时关闭线程池和处理异常。掌握这些能有效管理并发任务,避免性能瓶颈。
|
8天前
|
设计模式 运维 安全
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第15天】在Java开发中,多线程编程是提升应用程序性能和响应能力的关键手段。然而,它伴随着诸多挑战,尤其是在保证线程安全的同时如何避免性能瓶颈。本文将探讨Java并发编程的核心概念,包括同步机制、锁优化、线程池使用以及并发集合等,旨在为开发者提供实用的线程安全策略和性能优化技巧。通过实例分析和最佳实践的分享,我们的目标是帮助读者构建既高效又可靠的多线程应用。

热门文章

最新文章