java多线程基础小白指南--关键字识别(start,run,sleep,wait,join,yield)
在学习java多线程基础上,会遇到几个关键字,理解并识别它们是掌握多线程的必备知识,下面,我将通过源码或者程序演示给出我对这几个关键字的理解,如果有不同意见,欢迎在评论区或者发私信与我探讨。
一、start和run
常见的面试八股中(其实本人没遇到过。。。。)涉及多线程start和run时,面试官会问哪个方法才是真正启动线程的真正方法?答案很明显,其实是start,可以通过以下这个实现可以检验

run方法其实就是个普通方法,start方法才是jdk中Thread类中定义启动线程的真正方法,start的语义可以理解为告诉jvm在合适的时机启动这个线程,这里的合适时机不一定是调用完start线程就开始工作,而是在调度器决定,观察start的源码

start方法主要可以分为三步,在调用start方法后,会先检查这个线程的状态是不是NEW(注意看红色的注解,关于线程状态我会再开一篇文章),然后加入线程组,最后调用一个native方法start0
所以如果线程两次调用start方法的话,会出发一个IllegalThreadStateException
run方法的源码更为简单,这个方法更重要的在线程启动的几种形式中发光发热

二、sleep,wait,join,yield方法
这几个关键字比较乱,我们从作用,锁,线程状态进行分析。
- sleep方法查看源码可以知道这是个native方法,和cpp中sleep一样,它的作用是让线程进行休息,但是并不会释放掉锁(锁概念我会再开一篇文章讲述下synchronize关键字),线程sleep之后会处于TIME_WAITING状态,等待规定时间结束再运行,调用方式为Thread.sleep(时间)
- wait方法注意在Object类中通用方法,设计在Object中的原因我的理解是”任何对象都可以作为一把锁”,这样直接设计成Object方法就好,这里建议去阅读wait方法的注释,我这里就不翻译了,注意wait方法必须使用在同步方法中,源代码中推荐写成这种格式:

注意这个while!!!
放在同步方法块中是为了避免虚假唤醒和无效唤醒,wait方法的作用是让当前获得锁的线程进行等待(这里等待唤醒条件可以是时间消耗完了或者被其他线程唤醒锁),在wait后会释放掉锁,,对应不同的唤醒条件wait后也有两种不同的状态,如果有time限制,那就是TIME_WAITING,如果没有设置time,就是WAITING
更详细的介绍wait可以参考我的另一篇文章https://www.cnblogs.com/spark-cc/p/17074201.html - 验证sleep不会释放锁,wait会释放锁,同时sleep后状态是TIME_WAITING,wait状态是
点击查看代码
public class Wait {
public static Object object=new Object();
static class Thread1 extends Thread{
@Override
public void run(){
synchronized (object){
System.out.println(Thread.currentThread().getName()+"开始执行了");
try {
//Thread.sleep(600);
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"获得到了锁");
}
}
}
static class Thread2 extends Thread{
@Override
public void run(){
synchronized (object){
object.notify();
System.out.println("线程"+Thread.currentThread().getName()+"调用了notify");
}
}
}
public static void main(String[] args) throws InterruptedException{
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
Thread.sleep(500);
thread2.start();
}
}
注意sleep和wait的输出结果的顺序加以分析
- join方法的作用是让新线程加入当前线程,当前线程需要等待才能重新工作,比如如果主线程需要等待线程1工作完了才继续工作,那么就让线程1进行join即可,可以参考代码,注意注销join前后的输出变化
点击查看代码
public class Join {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
});
thread1.start();
thread2.start();
System.out.println("开始等待子线程运行完毕");
thread1.join();
thread2.join();
System.out.println("所有子线程已经执行完毕");
}
}
join也有两种用法,当有time参数时,主线程(这里说的是演示代码中的情况)状态为TIME_WAITING,没有time参数则为WAITING状态,同时也不会释放掉锁
join状态
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(mainThread.getState());
Thread.sleep(3000);
System.out.println("Thread-0 finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
thread.join(10000);
}
- yield方法用的比较少,是Thread的一个静态方法,它的作用是释放使用的cpu,不过它的状态依旧是RUNNABLE,同时也不会释放掉锁(好像没怎么用过,有没有大佬可以聊下使用场景)
java多线程基础小白指南--关键字识别(start,run,sleep,wait,join,yield)的更多相关文章
- Java 多线程基础(三) start() 和 run()
Java 多线程基础(三) start() 和 run() 通过之前的学习可以看到,创建多线程过程中,最常用的便是 Thread 类中的 start() 方法和线程类的 run() 方法.两个方法都包 ...
- java多线程基础(synchronize关键字)
[toc] 基础知识 ---- 线程:进程(process)就是一块包含了某些资源的内存区域.操作系统利用进程把它的工作划分为一些功能单元. 线程:进程中所包含的一个或多个执行单元称为线程(threa ...
- Java多线程编程实战指南(核心篇)读书笔记(五)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- 《Java多线程编程实战指南(核心篇)》阅读笔记
<Java多线程编程实战指南(核心篇)>阅读笔记 */--> <Java多线程编程实战指南(核心篇)>阅读笔记 Table of Contents 1. 线程概念 1.1 ...
- [转]Java多线程干货系列—(一)Java多线程基础
Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...
- Java 多线程——基础知识
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- Java多线程编程实战指南(核心篇)读书笔记(三)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76686044冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(二)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76651408冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(一)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76422930冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程基础知识总结
2016-07-18 15:40:51 Java 多线程基础 1. 线程和进程 1.1 进程的概念 进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程, ...
随机推荐
- 威纶通作为modbusTcp主站应用
1.在威纶通中添加modbus Tcp,作为主机,在Tcp服务器客户端模型中作为客户端: 2.威纶通地址与modbus标准功能码的对应关系: 地址1x_single_Bit,对应02功能码(读输入线圈 ...
- iOS包大小计算
一.LinkMap文件分析 说明:LinkMap数据是根据文章<LinkMap文件分析>中方法实验实测数据. 如何获得LinkMap文件 1.在XCode中开启编译选项Write Link ...
- CSS之 font
font:font-style font-weight font-size/line-height font-family的简写.顺序不能乱 **eg ** font:italic bold 30px ...
- 创建ZBLOG数据库
1.下载ZBLOG待测系统,并解压缩 打开内容如下 2.打开小皮面板的网站,点击网站->管理->打开根目录,然后把里面所有内容删除,粘贴下载好打开的内容 3.然后重启Nginx 4.浏览器 ...
- Erlang Mnesia数据库迁移方法
本文参考https://blog.csdn.net/yangzm/article/details/51686249 需求 因为一些原因,需要把一个Mnesia节点的数据库搬迁到另一个节点,然后弃用原来 ...
- docker 配置 anaconda + jupyter notebook 纪要
首先,pull官方的镜像,名字叫:continuumio/anaconda3 首先的首先,如果默认还是需要sudo运行docker命令,可以考虑把当前用户加入到docker组(usermod -aG ...
- centos7 升级gcc
#安装gcc yum install -y gcc-c++ autoconf automake #centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版 ...
- 十大经典排序之快速排序(C++实现)
快速排序 通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 思路: (1)选择基准:从数列中挑出一个 ...
- MySQL的卸载与安装
卸载 1.右键点击我的电脑 -->服务-->停掉MySQL的服务 2.控制面板卸载MySQL 3.删除隐藏文件夹 C:\ProgramData下的MySQL文件夹 4.删除MySQL文件夹 ...
- OSIDP-内存管理-07
专业术语 页框:内存中固定长度的块. 页:外存中固定长度的块. 段:外存中可变长度的块. 内存管理需求 重定位:程序从内存换出到外存后,再换回内存时,在内存空间中的位置和原先的位置有极大可能不相同.此 ...