• java多线程——线程通信


    一、线程通信目标

    1、线程通信的目标是使线程间能够互相发送信号

    2、线程通信使线程能够等待其他线程的信号

    二、几种方式

    1、通过共享对象

    2、忙等待

     线程 B 运行在一个循环里,以等待信号 (不释放cpu)

    3、wait,notify和notifyAll

    wait会使线程进入睡眠或者非运行状态,释放cpu使用权;

    线程必须在同步块里调用 wait()或者 notify();

    当一个线程调用一个对象的 notify()方法,正在等待该对象的所有线程中将有一个线程被唤醒并允许执行(校注:这个将被唤醒的线程是随机的,不可以指定唤醒哪个线程)。同时也提供了一个 notifyAll()方法来唤醒正在等待一个给定对象的所有线程;

    三、信号丢失

    notify()和 notifyAll()方法不会保存调用它们的方法,因为当这两个方法被调用时,有可能没有线程处于等待状态。通知信号过后便丢弃了。因此,如果一个线程先于被通知线程调用 wait()前调用了 notify(),等待的线程将错过这个信号。

    为了避免丢失信号,必须把它们保存在信号类里。

    四、假唤醒

    线程有可能在没有调用过 notify()和 notifyAll()的情况下醒来。这就是所谓的假唤醒(spurious wakeups)。

    为了防止假唤醒,保存信号的成员变量将在一个 while 循环里接受检查,而不是在 if 表达式里。这样的一个 while 循环叫做自旋锁(校注:这种做法要慎重,目前的 JVM 实现自旋会消耗 CPU,如果长时间不调用 doNotify 方法,doWait 方法会一直自旋,CPU 会消耗太大)。被唤醒的线程会自旋直到自旋锁(while 循环)里的条件变为 false。

    五、不要在字符串常量或全局对象中调用 wait()

    在空字符串作为锁的同步块(或者其他常量字符串)里调用 wait()和 notify()产生的问题是,JVM/编译器内部会把常量字符串转换成同一个对象;

    应该使用对应唯一的对象

  • 相关阅读:
    delphi 缓冲画图(内存画图)解决画图闪烁问题
    多重启动光盘制作
    Delphi源程序格式书写规范
    得到一个数据库的触发器的sql
    Querying Active Directory using .NET classes and LDAP queries(http://www.codeproject.com/dotnet/activedirquery.asp)
    My Friend Blog
    .net good study
    关于javascript的apply和call函数
    Microsoft command
    明基成人礼:巅峰战将营 http://www.cnvn.com.cn/Article/ShowArticle.asp?ArticleID=3172
  • 原文地址:https://www.cnblogs.com/lwcoding/p/6672829.html
Copyright © 2020-2023  润新知