首页 > 技术文章 > 线程中sleep()方法和wait()方法的前生今世

cxworkplace 2020-08-27 22:41 原文

先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索【程序职场】关注这个执着的职场程序员。
我有什么:职场规划指导,技能提升方法,讲不完的职场故事,个人成长经验。

 

 

不知道大家有没有这种感觉,在公司项目忙碌的时候,有时候感觉又忙又累,甚至加班通宵都有,能忙死人,每天想着轻松点吧,能休息休息做点别的什么。

但是当项目收尾不忙(不忙是指不用加班)的时候,如果一天两天还好,但是时间超出一周(不是没事干,是不像之前每天加班才能完成任务,现在每天8个小时不到就完成了任务),总是感觉太闲了,不太充实了,不知道该干什么。这边找点事,那边找点事

有时候甚至想着还是忙点吧。


所以趁着最近几天不是太忙,对自己做了一个复盘,发现我计划的东西还有一半没有完成(比如:我读的书 和 写的教程还只是做到2/1),所以还要加油,更主要的是 公众号文章的更新以后要保持下去。

好了不发感慨了,开始我们今天的线程篇(这些文章目前已经做了分类,多了就能成系统了)。

 

1,sleep和wait概念

Java中的多线程是一种抢占式的机制。
线程主要有以下几种状态:可运行,运行,阻塞,死亡。抢占式机制指有多个线程处于可运行状态,但是只有一个线程在运行。

当有多个线程访问共享数据的时候,就需要对线程进行同步。线程中的几个主要方法的比较:

 

Thread类的方法:sleep(),yield()等

Object的方法:wait()和notify()等

 

每个对象都有一个机锁来控制同步访问。Synchronized关键字可以和对象的机锁交互,来实现线程的同步。

由于sleep()方法是Thread类的方法,因此它不能改变对象的机锁

Wait()方法和notify()方法:当一个线程执行到wait()方法时(线程休眠且释放机锁),它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。

当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()前的中断现场。

共同点: 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。

不同点: Thread.sleep(long)可以不在synchronized的块下调用,而且使用Thread.sleep()不会丢失当前线程对任何对象的同步锁(monitor);

object.wait(long)必须在synchronized的块下来使用,调用了之后失去对object的monitor, 这样做的好处是它不影响其它的线程对object进行操作。

 

2. sleep和wait方法的应用场景

sleep 休眠方法:

Static void sleep(long ms)

该方法会使当前线程进入阻塞状态指定毫秒,当阻塞指定毫秒后,当前线程会重新进入Runnable状态,等待划分时间片。

wait方法一般是跟notify方法连用的:

多线程之间需要协调工作。如果条件不满足则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制实现依赖于wait/notify。

 

3,简单使用

一,Sleep()

  1. Sleep方法属于Thread类,调用Sleep时会暂停此线程指定的时间,但它的监控一直在监控着,Sleep不会释放对象的锁,到了一定时间它会自动唤醒。

  2. Sleep方法有接收时间参数,Therad.Sleep(1000)  其中参数都是毫秒值。

public class ThreadSleep {

public static void main(String[] args) {// write your code here

int time = 10;
for (int i=1;i<=time;i++) {

try {

Thread.sleep(1000);

System.out.println("线程休眠时间=" + i +"秒");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}


上面的代码循环中间隔一秒输出一个信息。

 

线程休眠时间=1秒
线程休眠时间=2秒
线程休眠时间=3秒
线程休眠时间=4秒
线程休眠时间=5秒
线程休眠时间=6秒
线程休眠时间=7秒
线程休眠时间=8秒
线程休眠时间=9秒
线程休眠时间=10秒

Process finished with exit code 0

 

二,Wait()

1.Wait()方法属于Object类,调用Wait方法时,线程会放弃对象锁,进入等待此对象的等待锁定池,只有此对象调用notify()方法后本线程才进入对象锁定池准备,wait方法需要被动唤醒,
2. wait方法不需要时间参数

public class ThreadWait {    public static void main(String[] args) {       
/**
* 作者:公众号:程序职场 * 代码描述:创建两个线程一个操作年龄的信息,一个是工作量的信息 */
//输出年龄信息

Object obj=new Object();

Thread download=new Thread(){


public void run() {

System.out.println("开始输出年龄");

for (int i = 1; i < 6; i+=1) {

System.out.println("年龄="+i);

}

System.out.println("年龄输出成功");

synchronized (obj) {

System.out.println("唤起");

obj.notify();//唤起wait的等待

}

System.out.println("开始输出工作量");


for (int i = 1; i < 6; i+=1) {

System.out.println("工作量="+i+"小时");

}

System.out.println("工作量输出成功");

}

};
//2.年龄输出成果的结果
Thread show=new Thread(){

public void run(){

synchronized (obj) {


try {

System.out.println("阻塞");

obj.wait();//阻塞当前

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("年龄完成");

}

}

};

download.start();

show.start();

}
}

1,show线程中阻塞线程(wait)​
2,download线程中 唤醒(notify)

本文 Github ( 码云Gitee同步) https://github.com/ProceduralZC/JavaDevGuide/tree/master/code/JavaTheead/ThreadClass  已收录,欢迎 star。

 

 

 

 

我是【尔东双月】一枚执着的职场程序员,微信搜索【程序职场】关注我。别忘了三连啊,点赞、收藏、留言,随意给,我不挑。
知乎号: 程序职场
注:如果文章有任何问题,欢迎毫不留情地指正。

推荐阅读