【线程系列三】线程的等待与唤醒机制

为了更高效的处理一些时间片短,任务量大的任务,我们可能会经常用到多线程。但是多线程的环境下,很容易出现线程并发问题,线程死锁就是很常见的一种并发问题。为了避免此类问题,我们会用到线程间的通信,而等待唤醒机制,就是线程间通信的一种形式。

等待唤醒机制用到的方法主要有:

public final void wait() throws InterruptedException
	当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。
wait()还有另外两个重载的方法 :
	wait(long timeout)、 wait(long timeout,int nanos)
public final void notify()
	唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;
	例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣。此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:
	1、通过执行此对象的同步实例方法。
	2、通过执行在此对象上进行同步的 synchronized 语句的正文。
	3、对于 Class 类型的对象,可以通过执行该类的同步静态方法。一次只能有一个线程拥有对象的监视器。
public final void notifyAll():
	唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;
	例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。此方法只应由作为此对象监视器的所有者的线程来调用。

需要注意:
	1、线程用到的锁对象可以是任意对象,这点从wait方法和notify方法可以看出来,因为它们是Object类的方法,而Object类是所有类的父类。
	2、上文中所提到的“监视器”即指“锁对象”。
	3、wait方法被调用时,线程进入阻塞状态,会释放所占用的资源,释放cpu执行权,抛出InterruptedException,这几点与sleep方法是相同的。但是与之不同的地方时,wati方法还会释放锁,而sleep方法不会。

线程的五态转换图:

时间: 2024-08-26 18:01:12

【线程系列三】线程的等待与唤醒机制的相关文章

线程系列09,线程的等待、通知,以及手动控制线程数量

当一个线程直到收到另一个线程的通知才执行相关的动作,这时候,就可以考虑使用"事件等待句柄(Event Wait Handles)".使用"事件等待句柄"主要用到3个类: AutoResetEvent, ManualResetEvent以及CountdownEvent(.NET 4.0以后才有).本篇包括: ※ 一个线程等待另一个线程的通知※ 2个线程互相通知等待※ 一个线程等待队列中的多个任务通知※ 手动控制线程的数量 □ 一个线程等待另一个线程的通知 最简单的情景

等待与唤醒机制(线程之间的通信)

线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 为什么要处理线程间通信 多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且我们 希望他们有规律的执行, 那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据. 如何保证线程间通信有效利用资源: 多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用或操作. 就是多个线程在操作同一份数据时, 避免对同一共享变量的

死磕 java线程系列之线程池深入解析——未来任务执行流程

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了线程池中普通任务的执行流程,但其实线程池中还有一种任务,叫作未来任务(future task),使用它您可以获取任务执行的结果,它是怎么实现的呢? 建议学习本章前先去看看彤哥之前写的<死磕 java线程系列之自己动手写一个线程池(续)>,有助于理解本章的内容,且那边的代码比较短小,学起来相对容易一些. 问题

死磕 java线程系列之线程模型

问题 (1)线程有哪些类型? (2)线程模型有哪些? (3)各语言是怎么实现自己的线程模型的? 简介 在Java中,我们平时所说的并发编程.多线程.共享资源等概念都是与线程相关的,这里所说的线程实际上应该叫作"用户线程",而对应到操作系统,还有另外一种线程叫作"内核线程". 用户线程位于内核之上,它的管理无需内核支持:而内核线程由操作系统来直接支持与管理.几乎所有的现代操作系统,包括 Windows.Linux.Mac OS X 和 Solaris,都支持内核线程.

C# 线程系列三 定时器线程

上一篇文章我们讲诉了自定义线程执行器和任务处理器 我们继续来讲解自定义线程的定时执行器,我们在很多场景下需要做到某些状态或者数据进行更新,如果事情很多很杂,很时候时候会创建很多不同的定时器那么势必会照成系统的消耗和性能低下的问题!今天我们来解决这一问题. 首先我们创建定时任务执行器基类 1 /// <summary> 2 /// 3 /// </summary> 4 public abstract class TimerTaskBase : BaseTask 5 { 6 7 8 /

死磕 java线程系列之线程池深入解析——定时任务执行流程

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:本文基于ScheduledThreadPoolExecutor定时线程池类. 简介 前面我们一起学习了普通任务.未来任务的执行流程,今天我们再来学习一种新的任务--定时任务. 定时任务是我们经常会用到的一种任务,它表示在未来某个时刻执行,或者未来按照某种规则重复执行的任务. 问题 (1)如何保证任务是在未来某个时刻才被执行? (2)如何保证任务按照某种规则重复执行? 来个栗子 创建一个定时线程池,用它来

死磕 java线程系列之线程池深入解析——构造方法

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 ThreadPoolExecutor的构造方法是创建线程池的入口,虽然比较简单,但是信息量很大,由此也能引发一系列的问题,同样地,这也是面试中经常被问到的问题,下面彤哥只是列举了一部分关于ThreadPoolExecutor构造方法的问题,如果你都能回答上来,则可以不用看下面的分析了. 问题 (1)ThreadPoolExecutor有几个构造方法? (2)ThreadPoolExecutor最长的构

死磕 java线程系列之线程池深入解析——生命周期

摘自:https://www.cnblogs.com/tong-yuan/p/11748887.html (手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 上一章我们一起重温了下线程的生命周期(六种状态还记得不?),但是你知不知道其实线程池也是有生命周期的呢?! 问题 (1)线程池的状态有哪些? (2)各种状态下对于任务队列中的任务有何影响? 先上源码 其实,在我们讲线程池体

死磕 java线程系列之线程池深入解析——体系结构

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 Java的线程池是块硬骨头,对线程池的源码做深入研究不仅能提高对Java整个并发编程的理解,也能提高自己在面试中的表现,增加被录取的可能性. 本系列将分成很多个章节,本章作为线程池的第一章将对整个线程池体系做一个总览. 体系结构 上图列举了线程池中非常重要的接口和类: (1)Executor,线程池顶级接口: (2)ExecutorService,线程池次级接口,对Executor做了一些扩展,增加一