概念
线程睡眠是使线程让出CPU的最简单的做法之一,线程睡眠的时候,会将CPU资源交给其他线程,以便能轮换执行,当睡眠一定时间后,线程会苏醒,进入可运行状态,而不是运行状态。
例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY
,另一个为MIN_PRIORITY
,如果没有sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。
总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
线程睡眠的方法是Thread.sleep(long millis)
和Thread.sleep(long millis, int nanos)
,均为静态方法。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。
那调用sleep休眠的哪个线程呢?简单说,哪个线程调用sleep,就睡眠哪个线程,即只能控制当前正在运行的线程。
虽然sleep使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized
同步块,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。
因此要谨慎在同步环境中使用sleep,因为它没有释放锁,其他线程还在等待。
测试1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| /** * Java多线程—睡眠 * */ public class Test { public static void main(String[] args) { Thread t1 = new MyThread1(); Thread t2 = new Thread(new MyRunnable()); t1.start(); t2.start(); } } class MyThread1 extends Thread { public void run() { for (int i = 0; i < 3; i++) { System.out.println("线程1第" + i + "次执行!"); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } class MyRunnable implements Runnable { public void run() { for (int i = 0; i < 3; i++) { System.out.println("线程2第" + i + "次执行!"); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } }
|
输出结果
1 2 3 4 5 6
| 线程1第0次执行! 线程2第0次执行! 线程2第1次执行! 线程1第1次执行! 线程2第2次执行! 线程1第2次执行!
|
测试2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| /*** * 同步环境中使用sleep * 测试线程sleep时候不会释放锁 */ public class Sleep extends Thread { private Lock lock; public Sleep() { } public Sleep(String name, Lock lock) { super(name); this.lock = lock; } @Override public void run() { lock.lock(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "\t" + i); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } lock.unlock(); } public static void main(String[] args) { Lock lock = new ReentrantLock(); Sleep[] list = new Sleep[2]; for (int i = 0; i < list.length; i++) { list[i] = new Sleep("thread" + i, lock); } for (int i = 0; i < list.length; i++) { list[i].start(); } } }
|
输出结果
1 2 3 4 5 6 7 8 9 10
| thread0 0 thread0 1 thread0 2 thread0 3 thread0 4 thread1 0 thread1 1 thread1 2 thread1 3 thread1 4
|