并发编程——线程中sleep(),yield(),join(),wait(),notify(),notifyAll()区别
前言
今天简单的讲一讲线程中sleep(),join(),yield(),wait(),notify(),notifyAll()这些方法的使用以及区别。
不过在讲这些方法之前,需要简单的介绍一下锁池和等待池的概念。
专栏推荐:
并发编程专栏
锁池和等待池
1.锁池
所有需要竞争同步锁的线程都会放在锁池当中,比如当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当前面的线程释放同步锁后锁池中的线程去竞争同步锁,当某个线程得到后会进入就绪队列进行等待cpu资源分配。
2.等待池
当我们调用wait()方法后,线程会放到等待池当中,等待池的线程是不会去竞争同步锁。只有调用了notify()或notifyAll()后等待池的线程才会开始去竞争锁,notify()是随机从等待池选出一个线程放到锁池,而notifyAll()是将等待池的所有线程放到锁池当中
sleep()
首先看一下sleep方法的源码,我们发现sleep是一个静态方法,它接受一个long类型的毫秒值参数,而且是一个本地方法(native修饰),而且会抛出InterruptedException(中断异常)。
sleep()这个方法的使用很简单,因为它是一个Thread的静态方法,所以就可以直接Thread.sleep(毫秒值),休眠指定的毫秒数。
1、使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会执行。但是时间到了之后线程会进入就绪队列,重新去竞争cpu资源。
2.sleep()会释放cpu资源,但是不会释放同步锁(类锁和对象锁)
例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。
总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
yield()
使当前正在执行的线程向另一个线程交出运行权。注意这是一个静态方法。
该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
1、yield()执行后线程直接进入就绪状态。
2、yield()会释放cpu资源,但是不会释放同步锁(类锁和对象锁)
join()
执行后线程进入阻塞状态,例如在线程B中调用线程A的join(),那线程B会进入到阻塞队列,直到join结束或中断线程B才开始进入阻塞队列。
可以实现一个线程的顺序执行。
*下面举一个小例子:
我排队打饭,smile女神来了,我让她先打饭,但是这个时候她男朋友来了,smile女神让他男朋友先打饭。呜呜呜~~~~*
public class UseJoin {
static class Smile implements Runnable {
private Thread thread;
public Smile(Thread thread) {
this.thread = thread;
}
public Smile() {
}
public void run() {
System.out.println("smile开始排队打饭.....");
try {
if(thread!=null) thread.join();
} catch (InterruptedException e) {
}
SleepTools.second(2);//休眠2秒
System.out.println(Thread.currentThread().getName()
+ " smile打饭完成.");
}
}
static class SmileBoyfriend implements Runnable {
public void run() {
SleepTools.second(2);//休眠2秒
System.out.println("smileBoyfriend开始排队打饭.....");
System.out.println(Thread.currentThread().getName()
+ " smileBoyfriend打饭完成.");
}
}
public static void main(String[] args) throws Exception {
SmileBoyfriend smileBoyfriend = new SmileBoyfriend();
Thread sbf = new Thread(smileBoyfriend);
Smile smile = new Smile(sbf);
Thread s = new Thread(smile);
s.start();//我排队打饭
sbf.start();//smile女神来了,但是这个时候她男朋友来了,smile女神让他男朋友先打饭
System.out.println("chaoCode开始排队打饭.....");
s.join();
Thread.sleep(2000);//让主线程休眠2秒
System.out.println(Thread.currentThread().getName() + " chaoCode打饭完成.");
}
}
执行结果,可想而知,抱抱可怜的自己。
wait()和notify()、notifyAll()
1、wait方法用于协调多个线程对共享数据的存取,所以必须在Synchronized语句块内使用
2、wait()方法使当前线程暂停执行并释放会cpu资源,以及同步锁(类锁和对象锁)
3、调用wait()后必须调用notify()或notifyAll()后线程才会从等待池进入到锁池,当我们的线程竞争得到同步锁后就会重新进入绪状态等待cpu资源分配
当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。
notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
注意:
1、这三个方法都是java.lang.Object的方法。
2、notif()方法要配合wait()方法使用,一般在wait()之后调用或者在线程结束时调用才会成功。
感谢诸君的观看,文中如有纰漏,欢迎在评论区来交流。如果这篇文章帮助到了你,欢迎点赞关注。
并发编程——线程中sleep(),yield(),join(),wait(),notify(),notifyAll()区别的更多相关文章
- 转:【Java并发编程】之十:使用wait/notify/notifyAll实现线程间通信的几点重要说明
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17225469 在Java中,可以通过配合调用Object对象的wait()方法和no ...
- 【Java并发编程】之十:使用wait/notify/notifyAll实现线程间通信的几点重要说明
在Java中,可以通过配合调用Object对象的wait()方法和notify()方法或notifyAll()方法来实现线程间的通信.在线程中调用wait()方法,将阻塞等待其他线程的通知(其他线程调 ...
- 并发编程学习笔记(12)----Fork/Join框架
1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...
- java并发编程 线程基础
java并发编程 线程基础 1. java中的多线程 java是天生多线程的,可以通过启动一个main方法,查看main方法启动的同时有多少线程同时启动 public class OnlyMain { ...
- java线程中的sleep/wait/notify/yield/interrupt方法 整理
java线程中的sleep/wait/notify/yield/interrupt方法 sleep 该方法能够使当前线程休眠一段时间 休眠期间,不释放锁 休眠时间结束之后,进入可执行状态,加入到线程就 ...
- Java 并发编程 | 线程池详解
原文: https://chenmingyu.top/concurrent-threadpool/ 线程池 线程池用来处理异步任务或者并发执行的任务 优点: 重复利用已创建的线程,减少创建和销毁线程造 ...
- Python并发编程-线程同步(线程安全)
Python并发编程-线程同步(线程安全) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 线程同步,线程间协调,通过某种技术,让一个线程访问某些数据时,其它线程不能访问这些数据,直 ...
- 读Java并发编程实践中,向已有线程安全类添加功能--客户端加锁实现示例
在Java并发编程实践中4.4中提到向客户端加锁的方法.此为验证示例,写的不好,但可以看出结果来. package com.blackbread.test; import java.util.Arra ...
- java多线程之yield,join,wait,sleep的区别
Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...
随机推荐
- 前端 JavaScript 实现一个简易计算器
前端使用 JavaScript 实现一个简易计算器,没有难度,但是里面有些小知识还是需要注意的,算是一次基础知识回顾吧. 题目 实现一个简易版的计算器,需求如下: 1.除法操作时,如果被除数为0,则结 ...
- Tomcat:tomcat部署war包配置SSL访问
Linux-CentOS7部署 war放置 war放到tomcat的webapps目录内 修改配置 修改tomcat的server.xml文件 HTTP: 找到Connector元素,修改端口 HTT ...
- Extjs中由于ID重复引起的各种异常的解决方法
很多人使用EXTJS中的Tabpanel遇到一个问题: 那就是在点击Tabpanel后,有时会发现Tabpanel出现错误,或无法Destroy已经关闭的panel,发现已经关闭的panel 中的组件 ...
- SpringMVC(12)完结篇 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现
到这里已经写到第12篇了,前11篇基本上把Spring MVC主要的内容都讲了,现在就直接上一个项目吧,希望能对有需要的朋友有一些帮助. 一.首先看一下项目结构: InfrastructureProj ...
- 构建自己的dockerfile
一)创建自己的CentOS 构建dockerfile的原理图 Docker Hub中99%的镜像都是从FROM scratch这个基础镜像过来的.然后配置需要的软件和配置来进行构建. FROM #基础 ...
- hugo + nginx 搭建博客记录
作为一个萌新Gopher,经常逛网站能看到那种极简的博客,引入眼帘的不是花里胡哨的图片和样式,而是黑白搭配,简简单单的文章标题,这种风格很吸引我.正好看到煎鱼佬也在用这种风格的博客,于是卸载了我的wo ...
- linux驱动之获取设备树信息
上一篇文章学习了字符设备的注册,操作过的小伙伴都知道上一篇文章中测试驱动时是通过手动创建设备节点的,现在开始学习怎么自动挂载设备节点和设备树信息的获取,这篇文章中的源码将会是我以后编写字符驱动的模板. ...
- Linux | 命令的参数
命令的参数 格式:command parameters --> 命令参数 短参数 在短参数中,字母的大写效果是不同的,比如大写 T 和小写 t 的含义通常是不同的. 一个短参数 最常用的参数形式 ...
- Kong Admin API — 核心对象
目录 Service API详解 1. 添加服务 2. 列出service列表 3. 查找service 按条件查找service 查找与指定route关联的service 查找与指定Plugin关联 ...
- 如何少走弯路安装NLTK?
NLP中分词是一件麻烦事,nltk可以一定程度上优雅的解决一些需求 如果你去搜索"nltk安装",那么多半会得到以下的代码 import nltk nltk.download() ...