Java多线程编程核心技术( 四 )


一句话总结:wait让线程停止运行 , 使停止的线程继续运行 。
18.2 可以将任何一个对象作为同步对象来看待 , 而java为每个都实现了wait(0和() , 他们必须用在被同步的临界区内 。通常调用wait(0可以使处于临界区的线程进入等待状态 , 同时释放被同步对象的锁 。
而()操作可以唤醒一个因调用了wait()操作而处于阻塞状态中的线程 , 使其进入就绪状态 。被重新唤醒的线程会试图重新获得临界区的控制权 , 也就是锁 , 并继续执行临界区内wait之后的代码 , 如果发出操作时没有处理阻塞状态中的线程 , 那么该命令会被忽略 。
wait()可以调用该方法的线程释放共享资源的锁 , 然后从运行状态退出 , 进入等待队列 , 直到被再次唤醒 。
()可以随机唤醒等待队列中等待同一共享资源的“一个”线程 , 并使该线程退出等待队列 , 进入可运行状态 , 仅仅通知一个线程 。
()可以使所有正在等待队列中等待同一资源的“全部”线程从等待状态退出 , 进入可运行状态 , 此时优先级最高的那个线程最先执行 , 但也可能是随机执行 。这取决于jvm虚拟机的实现 。

Java多线程编程核心技术

文章插图
线程执行步骤:
1.新创建一个新的线程对象后 , 在调用他的start() , 系统会为此线程分配CPU资源 , 使其处于(可运行)状态 , 这是一个准备运行阶段 , 如果线程抢占到CPU资源 , 此线程就处于(运行)状态 。
2.状态和状态可相互切换 , 因为有可能线程运行一段时间后 , 有其他高优先级的线程抢占了CPU资源 , 此时线程就从状态切换到状态 。
线程进入的5种情况:
1.调用sleep()后经过的时间超过了指定的休眠时间
2.线程调用的阻塞IO已经返回 , 阻塞方法执行完毕
3.线程成功的获得了试图同步的监视器
4.线程正在等待某个通知 , 其他线程发出了通知
5.处于挂起状态的线程调用了回复方法 。
3.是阻塞的意思 , 例如遇到了一个IO操作 , 此时CPU处于空闲状态 , 可能会转而把CPU时间片分配给其他线程 , 这时也可称为“暂停”状态 , 结束后 , 进入状态 , 等待系统重新分配资源 。
出现阻塞的5中情况:
1.线程调用sleep() , 主动放弃占用的处理器资源
2.线程调用了阻塞式IO , 在该方法返回前 , 线程被阻塞
3.线程试图获得一个同步监视器 , 但该同步监视器正被其他线程所持有
4.线程等待某个通知
5.程序调用了方法将该线程挂起 , 此方法容易导致死锁 , 尽量避免使用 。
4.run()方法运行结束后进入销毁阶段 , 整个线程执行完毕 。
每个锁对象都有两个队列 , 一个就绪队列 , 一个阻塞队列 。就绪队列存储了将要获得锁的线程 , 阻塞队列存储了被阻塞的线程 。一个线程被唤醒后 , 才会进入就绪队列 , 等待CPU调度 , 反之 , 一个线程被wait后 , 就会进入阻塞队列 , 等待下一次被唤醒 。
18.3 wait()被执行后 , 锁自动被释放;()执行后 , 锁却不会自动释放(仅仅是通知) 。
18.4 ()遇到wait()
当线程呈wait状态 , 调用线程的()会抛出异常 。