Java 多线程基础(七)线程休眠 sleep
一、线程休眠 sleep
sleep() 方法定义在Thread.java中,是 static 修饰的静态方法。
sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。
二、sleep示例
public class SleepTest { private static Object obj = new Object(); public static void main(String[] args) { Thread t1 = new MyThread("t1"); t1.start(); } static class MyThread extends Thread{ public MyThread(String name) { super(name); } public void run() { synchronized (obj) { try { for(int i = 0;i < 5;i++) { System.out.println(Thread.currentThread().getName() + "--" + i); if (i % 4 == 0) Thread.sleep(1000);// i能被4整除时,休眠1秒 } }catch(Exception e) { e.printStackTrace(); } } } } }
// 运行结果 t1--0 t1--1 t1--2 t1--3 t1--4
说明:
在主线程main中启动线程t1。t1启动之后,当t1中的计算i能被4整除时,t1会通过Thread.sleep(100)休眠100毫秒。
三、sleep(long millis) 与 wait(long timeout)
我们知道,wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
但是,wait() 会释放对象的同步锁,而 sleep() 则不会释放锁。
通过下面的代码,演示 sleep() 不会释放锁的:
public class SleepTest { private static Object obj = new Object(); public static void main(String[] args) { Thread t1 = new MyThread("t1"); Thread t2 = new MyThread("t2"); t1.start(); t2.start(); } static class MyThread extends Thread{ public MyThread(String name) { super(name); } public void run() { synchronized (obj) { try { for(int i = 0;i < 5;i++) { System.out.println(Thread.currentThread().getName() + "--" + i);
Thread.sleep(1000);// 休眠1秒 } }catch(Exception e) { e.printStackTrace(); } } } } }
// 执行结果 t1--0 t1--1 t1--2 t1--3 t1--4 t2--0 t2--1 t2--2 t2--3 t2--4
说明:
主线程main中启动了两个线程t1和t2。t1和t2在run()会引用同一个对象的同步锁,即synchronized(obj)。在t1运行过程中,虽然它会调用Thread.sleep(1000) 进入休眠状态;但是,t2是不会获取CPU执行权的。因为,t1并没有释放“obj所持有的同步锁”!
注意,若我们注释掉 synchronized (obj) 后再次执行该程序,t1和t2是可以相互切换执行的,原因是:在没有同步锁的情况下,当一个线程进入“休眠(阻塞)状态“时,会放弃CPU的执行权,另一个线程就会获取CPU执行权。
通过下面的代码,演示 wait() 会释放锁的:
public class SleepTest { private static Object obj = new Object(); public static void main(String[] args) { Thread t1 = new MyThread("t1"); Thread t2 = new MyThread("t2"); t1.start(); t2.start(); } static class MyThread extends Thread{ public MyThread(String name) { super(name); } public void run() { synchronized (obj) { try { for(int i = 0;i < 5;i++) { System.out.println(Thread.currentThread().getName() + "--" + i); obj.wait(1000);// 等待1秒 } }catch(Exception e) { e.printStackTrace(); } } } } }
// 执行结果 t1--0 t2--0 t1--1 t2--1 t2--2 t1--2 t2--3 t1--3 t2--4 t1--4
说明:
主线程main中启动了两个线程t1和t2。t1和t2在run()会引用同一个对象的同步锁,即synchronized(obj)。在t1运行过程中,调用 obj.wait(1000) 进入等待状态,释放同步锁;此时,t2会获取CPU执行权的。