1.概述

使用Thread相对来说比较简单,没有什么成本,但是通常来说,我们使用线程基本就是覆写run方法,然后调用线程对象的start函数启动线程。

对于面试人员来说,这些都不是面试官会问到的问题,而线程的wait、sleep、join、yied这几个函数可问的就比较多了。

函数名 作用
wait    

当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁,使得其他线程可以访问。用户可以使用notify、notifyAll或者指定睡眠时间来唤醒当前等待池中的线程。

注意:wait()、notify()、notifyAll()必须放在synchronized block中,否则会抛出异常

sleep    该函数是Thread的静态函数,作用是使调用线程进入睡眠状态。因为sleep()是Thread类的Static方法,因此他不能改变对象的机锁。所以,当在一个Sychronized块中调用sleep()方法,线程虽然休眠了,但是对象的机锁并没有释放,其他线程无法访问这个对象(即使睡着也持有对象锁)
join 等待目标线程执行完成之后再继续执行
yield 线程礼让。目标线程由运行状态转换为就绪状态,也就是让出执行权限,让其他线程得以优先执行,但其他线程能否优先执行是未知数

2.实际运用

(1)wait、notify

public class ThreadFunTest {
private static Object sLockObject = new Object(); static void waitAndNotifyAll() {
System.out.println("主线程运行");
Thread thread = new WaitThread();
thread.start();
long startTime = System.currentTimeMillis();
try {
synchronized (sLockObject) {
System.out.println("主线程等待");
sLockObject.wait();
}
} catch (Exception ignored) { }
long timsMs = (System.currentTimeMillis() - startTime);
System.out.println("主线程继续-->等待耗时:" + timsMs + "ms");
} static class WaitThread extends Thread {
@Override
public void run() {
try {
synchronized (sLockObject) {
Thread.sleep(3000);
sLockObject.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
ThreadFunTest.waitAndNotifyAll();
}
}

执行结果:

在waitAndNotifyAll()函数中,会启动一个WaitThread线程,在该线程中将会调用sleep函数睡眠3秒,线程启动后在主线程调用sLockObject的wait函数,使主线程进入等待状态,此时将不会继续执行。等WaitThread在run函数睡眠3秒后会调用sLockObject的notifyAll函数,此时就会重新唤醒正在等待中的主线程,因此会继续执行下去。

 wait、notify机制通常用于等待机制的实现,当条件为满足时调用wait进入等待状态,一旦条件满足,调用notify或notifyAll唤醒等待的线程继续执行。

(2)join

与wait、sleep的浅显易懂不同的是join的作用并不那么直观,也许就是这个原因,使得join函数并不那么容易理解。join函数的原始解释为”Blocks the current Thread(Thread.currentThread())until the receiver finishes its execution and dies“,意思就是阻塞当前调用join函数时所在的线程,直到接收线程执行完毕后再继续。

static void joinDemo() {
Worker worker1 = new Worker("work-1");
Worker worker2 = new Worker("work-2");
worker1.start();
System.out.println("启动线程1");
try{
//调用work1的join函数,主线程会阻塞直到work1执行完成
worker1.join();
System.out.println("启动线程2");
//再启动线程2,并且调用线程2的join函数,主线程会阻塞直到worker2执行完成
worker2.start();
worker2.join();
}catch (Exception ignored){ }
System.out.println("主线程继续执行");
} static class Worker extends Thread {
public Worker(String name) {
super(name);
} @Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work in " + getName());
}
} public static void main(String[] args) {
ThreadFunTest.joinDemo();
}

执行结果:

这是因为再joinDemo函数中,首先创建了两个子线程,然后启动了worker1,下一步再调用worker1的join函数。此时主线程进入阻塞状态,一直到worker1执行完毕后才开始继续执行。因为Worker的run函数会睡眠2秒,因此,在主线程中每次调用join实际上都会阻塞2秒,直到run执行完毕再继续。所以,上述逻辑为启动线程1--等待线程1执行完成--启动线程2--等待线程2执行完成--继续执行主干代码。

(3)yied

yied函数与join类似,官方解释为”Causes the calling Thread to yield execution time to another Thread that is read to run“。意思是使调用该函数的线程让出执行时间给其他已经就绪状态的线程。我们知道,线程的执行是有时间片的,每个线程轮流占用CPU固定的时间,执行周期到了之后就让出执行权给其他线程。而yield的功能就是主动让出线程的执行权给其他线程,其他线程能否得到优先执行就得看各个线程的状态了。示例:

static void yieldDemo() {
YieldThread t1 = new YieldThread("thread-1");
YieldThread t2 = new YieldThread("thread-2");
t1.start();
t2.start();
} static class YieldThread extends Thread {
public YieldThread(String name) {
super(name);
}
public synchronized void run() {
for (int i = 0; i < 5; i++) {
System.out.println(String.format("%s [%d] ---> %d", this.getName(), this.getPriority(), i));
//当i为2时调用当前线程的yield函数
if (i == 2) {
Thread.yield();
}
}
}
} public static void main(String[] args) {
ThreadFunTest.yieldDemo();
}

执行结果:

通常情况下t1首先执行,让t1的run函数执行到i等于2时让出当前线程的执行时间,因此,我们看到执行到的thread-2  等于2之前交替执行,等于2时,thread-2让出执行时间,执行thread-1,thread-1执行到2时又将执行权让出,执行thread-2直到完毕再开始执行thread-1.

调用yield就是让出当前线程的执行权,这样一来就王其他线程得到优先执行。

【java线程】的wait、sleep、join、yied的更多相关文章

  1. Java线程中yield与join方法的区别

    长期以来,多线程问题颇为受到面试官的青睐.虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用.之前,我讨论了一个w ...

  2. Java线程与多线程教程

    本文由 ImportNew - liken 翻译自 Journaldev.   Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用 ...

  3. Java线程小刀牛试

    线程简介 什么是线程 现代操作系统调度的最小单元是线程,也叫轻量级进程(Light Weight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器.堆栈和局部变量等属性,并且 ...

  4. java 笔记(5) —— 线程,yield,join

    一.线程各个状态与转换: 新建状态:用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存 .就绪状态:当一个线程创建了以后,其他的线程调用了它的start() ...

  5. Java线程状态及 wait、sleep、join、interrupt、yield等的区别

    Java中的线程状态(详见Java线程状态及转换-MarchOn): wait:Object类的实例方法,释放CPU执行权,进入等待状态,直到  被中断.被拥有该对象锁的线程唤醒(notify或not ...

  6. java线程join方法使用方法简介

    本博客简介介绍一下java线程的join方法,join方法是实现线程同步,可以将原本并行执行的多线程方法变成串行执行的 如图所示代码,是并行执行的 public class ThreadTest { ...

  7. (Java多线程系列六)join()的用法和线程的优先级

    join()的用法和线程的优先级 1.join()的用法 join()作用就是让其他线程处于等待状态 先看一个需求:创建一个线程,子线程执行完毕后,主线程才能执行 public class JoinT ...

  8. java 多线程 Thread.join子线程结束父线程再运行;join(long):等待超时毫秒数

    Join的使用 目的:当子线程运行结束后,父线程才能再继续运行 /** * @ClassName ThreadJoinExample * @projectName: object1 * @author ...

  9. Java线程的概念

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

  10. 【转载】 Java线程面试题 Top 50

    Java线程面试题 Top 50 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员 的欢迎.大多数待遇丰厚的J ...

随机推荐

  1. java之Spring(AOP)-Annotation实现添加切面

    我们已经知道之前的切面添加方式(动态代理),是定义了一个实现了InvocationHandler接口的Handlerservice类,然后 在这个类内部写好切面逻辑,包括切面放置的位置,很显然下面的这 ...

  2. nginx基本配置参数说明

    #运行用户 user nobody; #启动进程,通常设置成和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 #error_log logs/error.log; ...

  3. php获取汉字首字母实例

    在我们实际开发工作中,有时候需要获取输入汉字的首字母,然后存到库中,方便用户搜索相关信息,下面给出php代码,留做备用: //新添加获取汉子首字,首字字母 function pinyin($zh){ ...

  4. 通过jstack与jmap分析一次cpu打满的线上故障

    一.发现问题 下面是线上机器的cpu使用率,可以看到从4月8日开始,随着时间cpu使用率在逐步增高,最终使用率达到100%导致线上服务不可用,后面重启了机器后恢复. 二.排查思路 简单分析下可能出问题 ...

  5. 关于office在卸载了某一应用之后无法试图使用的功能所在的网络位置

    我出现这个问题是在卸载了某一个微软的办公软件之后,所有的办公软件都会产生这个问题. 处理的方法是将之前的安装包解压,然后找到所出现的msi文件,点击确定就ok了. 所以说,安装文件最好还是放在一个地方 ...

  6. 第二章:第一个Netty程序

    第一步:设置开发环境 • 安装JDK,下载地址http://www.oracle.com/technetwork/java/javase/archive-139210.html   • 下载netty ...

  7. Eclipse从数据库逆向生成Hibernate实体类和映射文件(Eclipse插件系列之HibernateTools)

    ♣下载安装Eclipse插件(HibernateTools) ♣Eclipse连接数据库(Mysql5.7) ♣新建hibernate.properties和hibernate.cfg.xml文件 ♣ ...

  8. 实现pc端信纸留言板

    效果如图: 我好像在哪里见过这样的形式,但却从来没有想过怎么实现,有种莫名的兴奋感.怎么控制什么时候换行,怎么控制中间的线条,这些视乎都是CSS无法实现的,我陷入了死局.寻找JS的做法,JS的挺复杂的 ...

  9. SSM-SpringMVC-13:SpringMVC中XmlViewResolver视图解析器

     ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 还记得上篇博客提出来的问题吗? BeanNameViewResolver视图解析器每使用一道视图,就得手工配 ...

  10. CS224n笔记0

    我准备跟随码农场hankcs大神的脚步,学习一下斯坦福的CS224n课程. 关于该课程的简介,hankcs大神已经写得很清楚了.