Java中关于Thread.sleep()与 线程对象.sleep()的思考

前言:java中Thread线程类中的sleep()查看API文档如下:

static void (long millis) 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 static void (long millis, int nanos) 导致正在执行的线程以指定的毫秒数加上指定的纳秒数来暂停(临时停止执行),这取决于系统定时器和调度器的精度和准确性。

得知该方法为静态方法,返回值为void,并且有两种传参方式,作用是使当前正在执行的线程以指定的毫秒数暂停,进入睡眠阻塞状态,放弃CPU时间片执行权。

然后我不禁陷入了思考:为啥是静态方法,静态方法一般可用类名直接调用。但是我如果创建一个线程对象,然后用该对象来调用该静态方法会产生咋样的结果?

1.首先,我先用类名直接调用,代码如下:

import java.lang.Thread;
public class ThreadTest03{
	public static void main(String[] args) 
	{
		//创建分支线程对象
        Thread t3=new MyThread03();
        //类名.sleep()
		try{ 
			Thread.sleep(1000*5);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
        t3.start(); //启动分支线程
    }
        
}
class MyThread03 extends Thread{
	public void run(){
		for(int i=0;i<100;i++)
			System.out.println("当前分支线程--->"+i);
	}
}

Thread.sleep()的作用就是让当前线程进入睡眠,请注意了,是当前线程对象,这个“当前”就很微妙哈哈,有点类似于关键字“this”。通俗解释是:Thread.sleep()出现在哪里,那么哪里就得sleep!

你看,上面的Thread.sleep()不是出现在main方法中吗,所以自然而然 主线程这个“倒霉蛋”只能乖乖的睡眠1000*5ms=5s后再继续执行下一条代码t3.start(),然后才开启分支线程。

2.然后,那如果我想要t3这个线程对象sleep一段时间,那要咋做呢,我立马想到了把Thread.sleep(1000*5)改成t3.sleep(1000*5)岂不是大功告成了?

import java.lang.Thread;
public class ThreadTest03{
	public static void main(String[] args) 
	{
		//创建分支线程对象
        Thread t3=new MyThread03();
        //线程对象.sleep()
		try{ 
            //在main中,我想这样让t3睡眠行不行
			t3.sleep(1000*5);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
        t3.start(); //启动分支线程
    }
        
}
class MyThread03 extends Thread{
	public void run(){
		for(int i=0;i<100;i++)
			System.out.println("当前分支线程--->"+i);
	}
}

实际上,在main线程中使用另一个线程对象t调用sleep()方法是无法达到使得t线程对象sleep的目的的!

原因如下: 在静态方法中, 对象.静态方法 最终会自动转换为类名.静态方法 。

就比如,我定义了一个“人”类,定义了这个类的一个静态方法:“打闪电五连鞭”,然后我创建了一个对象“马保国”, 这个对象去调用静态方法:马保国.打闪电五连鞭。最终执行时会自动转换成 人.打闪电五连鞭 ,表面上看起来是马保国打,实际上并不是。(这时候马保国开始说了:年轻人不讲武德,你骗,欺负我一个69岁的老人。)

所以, t3.sleep()最终会自动转换为Thread.sleep()执行(代表当前对象进入睡眠),表面上是t3进入sleep,实际上还是主线程main进入睡眠5s。

sleep()设置为静态方法的目的: 如果让sleep()成为实例方法,当前线程可以直接sleep别的线程,会引入很多多线程的问题,比如死锁。

所以最终得出结论:只能控制当前正在运行的线程,跟对象调用还是类名调用无关,只看你sleep()出现的位置。

参考学习视频:

经验分享 程序员 微信小程序 职场和发展