Thread类的静态方法在多线程中是高频出现的。虽然都知道每个方法,但是具体的实际应用中,一些方法细节与自己想象中的还是有些出入的。在此,将平时所遇到的一些相关知识点,记录一下。实时更新。
sleep()
sleep(long millis)
,sleep(long millis,int nanos)
。相关文档中描述如下
大家熟知的定义:
sleep()方法是线程用来控制自身流程的,通过该方法可以使当前线程休眠/暂停执行一段时间,并把执行机会让给其他线程。
注意点:
sleep()
方法的休眠时间millis,当指定毫秒数时间一到,线程就会被自动唤醒。但不是意味着这个线程马上就开始运行了。而是重新返回到可运行状态,然后等待CPU调度执行。所以一个线程在sleep(millis)后,重新获得CPU的控制的时间一定大于等于millis。sleep()
方法必须捕获异常,根据上面的文档截图我们也可以看到,该方法是声明了一个异常的。所以当你使用的时候,必须捕获。sleep()
方法并不会释放锁。记住,当在同步代码块中使用sleep()方法,该线程虽然暂停执行一段时间,但是它并没有释放锁,就是说资源状态并不发生改变。这里可能有点绕,直接上代码。
package com.study;
public class TestSleep {
public static void main(String[] args) {
TestData data = new TestData();
Thread thread1 = new Thread(new MyThread(data),"mythread1");
Thread thread2 = new Thread(new MyThread(data),"mythread2");
thread1.start();
thread2.start();
}
}
class MyThread implements Runnable{
private TestData data;
public MyThread(TestData data){
this.data = data;
}
public void run() {
//System.out.println(Thread.currentThread().getName()+"开始执行");
data.print(Thread.currentThread().getName());
//System.out.println(Thread.currentThread().getName()+"执行结束");
}
}
package com.study;
public class TestData {
public synchronized void print(String str){
System.out.println(Thread.currentThread().getName()+"开始打印:"+str);
System.out.println(Thread.currentThread().getName()+"开始sleep()");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"sleep()结束");
}
}
我们可以看到,线程1和2共享一个资源(TestData对象)。在运行结果中我们可以看到,线程2首先获得资源,开始运行。然后线程2暂停执行,但是线程1并没有获得资源开始执行,而是在线程2等待10秒以后,重新苏醒,继续完成任务并结束后,线程1才开始。
举个栗子,就如同甲乙两人在合租,共用一个洗衣机。甲乙两人看今天天气好,都要洗衣服晒一下。但是甲先一步开始用洗衣机,乙便过来等待甲洗完再自己洗。结果甲在中途突然困了,想去睡会,把洗衣机暂停了,然后就去睡了。但是这个时候乙还是没法洗,因为甲把衣服还放在洗衣机里面,占用着资源。乙不好意思说,就算了,一直等甲起来。后面甲醒了继续洗。这时等甲洗完以后,乙才开始洗衣服。
但是,如果多个线程之间,并没有“锁关系”,那么线程1执行sleep()方法后,其他线程便会开始执行。
代码如下。
package com.study;
public class TestSleep {
public static void main(String[] args) {
Thread t1 = new Thread(new myThread(), "thread1");
Thread t2 = new Thread(new myThread(), "thread2");
t1.start();
t2.start();
}
}
class myThread implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName()+"开始执行");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行结束");
}
}
通过上面两种情况对比,对sleep()
方法就有个比较清晰的认识了。它会让线程暂停,释放占有的CPU资源,让别的线程去抢夺CPU资源执行。但是它并不会释放线程所占用的锁资源。