目录:
- sleep()
- wait()
- notify()/notifyAll()
- yieid()
- join()
- 总结
sleep():
1、sleep()方法的作用是让线程暂停指定的毫秒数
2、sleep()方法只是暂时交出CPU的执行权,并非释放锁
3、sleep()方法不需要在synchronize块中执行,而wait()方法需要
4、sleep()可以通过interrupt()方法打断休眠状态
5、sleep()只是操作线程,并不涉及线程间的通信
1 public class SleepTest { 2 /** 3 * sleep()方法不会释放锁,因此线程是按照先后顺序执行的 4 */ 5 public synchronized void sleepMethod() { 6 System.out.println("Sleep start : " + Thread.currentThread().getName()); 7 try { 8 Thread.sleep(1000); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 System.out.println("Sleep end : " + Thread.currentThread().getName()); 13 } 14 15 /** 16 * wait()方法会释放锁,因此一旦调用wait()方法就会造成其他线程运行 17 */ 18 public synchronized void waitMethod() { 19 System.out.println("Wait start : " + Thread.currentThread().getName()); 20 try { 21 wait(1000); 22 } catch (InterruptedException e) { 23 e.printStackTrace(); 24 } 25 26 System.out.println("Wait end :" + Thread.currentThread().getName()); 27 } 28 29 public static void main(String[] args) { 30 final SleepTest test1 = new SleepTest(); 31 for (int i = 0; i < 5; i++) { 32 new Thread(() -> test1.sleepMethod()).start(); 33 } 34 35 try { 36 // 暂停十秒,等上面程序执行完成 37 Thread.sleep(10000); 38 } catch (InterruptedException e) { 39 e.printStackTrace(); 40 } 41 42 System.out.println("-----分割线-----"); 43 44 final SleepTest test2 = new SleepTest(); 45 for (int i = 0; i < 5; i++) { 46 new Thread(() -> test2.waitMethod()).start(); 47 } 48 } 49 }
sleep都是一个一个执行完,先start再end,从这一现象便知sleep()方法并不会释放锁;而wait则不会交出CPU的执行权。
若将18行的synchronize删除,wait()方法便会抛出IllegalMonitorStateException异常,所以wait()方法必须要在synchronize块中执行。
wait():
1、wait()\notify()方法通常成对出现
2、wait()\notify()方法都需要在synchronize块中执行
3、wait()方法可以通过interrupt()方法打断暂停状态
4、通过为wait()方法设置时间(wait(1000))或调用notify()方法可以让对象重新获取锁
notify()/notifyAll():
1、notify()用户唤醒此对象上等待的单个线程,notifyAll()唤醒多个线程
2、notifyAll()唤醒的顺序为先进后出,Last In First Out
3、wait()/notify()/notifyAll()涉及线程间的通信
1 public class WaitClassDemo { 2 3 private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 4 5 public static void main(String[] args) { 6 Object obj = new Object(); 7 for (int i = 0; i < 5; i++) { 8 new WaitThread(i + "", obj).start(); 9 } 10 new NotifyThread(obj).start(); 11 } 12 13 /** 14 * 调用wait()方法的线程 15 */ 16 static class WaitThread extends Thread { 17 Object obj; 18 public WaitThread(String name, Object obj) { 19 setName("WaitThread" + name); 20 this.obj = obj; 21 } 22 23 @Override 24 public void run() { 25 synchronized (obj) { 26 System.out.println(sdf.format(new Date()) + " " + getName() + " before wait()"); 27 try { 28 obj.wait(); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 System.out.println(sdf.format(new Date()) + " " + getName() + " after wait()"); 33 } 34 } 35 } 36 37 /** 38 * 调用notify()/notifyAll() 39 */ 40 static class NotifyThread extends Thread { 41 Object obj; 42 public NotifyThread(Object obj) { 43 setName("NotifyThread"); 44 this.obj = obj; 45 } 46 47 @Override 48 public void run() { 49 synchronized (obj) { 50 try { 51 Thread.sleep(5000); 52 } catch (InterruptedException e) { 53 e.printStackTrace(); 54 } 55 System.out.println(sdf.format(new Date()) + " NotifyThread before notify()"); 56 // 唤醒所有线程 用notifyAll()会按照后进先出(LIFO)的原则恢复线程 57 obj.notifyAll(); 58 try { 59 Thread.sleep(5000); 60 } catch (InterruptedException e) { 61 e.printStackTrace(); 62 } 63 System.out.println(sdf.format(new Date()) + " NotifyThread after notify()"); 64 } 65 } 66 } 67 }
yieId():
1、作用:告诉CPU你这次分给我的资源我不要了,你去给其它线程吧( ̄︶ ̄)↗
2、注意:
)yieId()方法不能保证其它线程一定能够执行,因为它仍是可执行状态,所以仍有可能被CPU再次执行
)执行yieId()方法不会释放锁
join():
1、作用:让一个线程在另一个线程执行完后再执行
2、注意:线程A内部执行线程B的join()方法,那么A将会阻塞,直到线程B执行完后才会执行线程A
3、Demo:小明点了一个煎饼果子,老板收到订单后便开始做煎饼;那小明肯定是不可能在煎饼果子来之前啥事都不做,老板也一样;所以我们这里用线程来实现他们两个的动作。
1 public class Consumer { 2 3 public void eat() { 4 System.err.println("开始吃煎饼果子..."); 5 try { 6 Thread.sleep(1000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 System.err.println("煎饼果子吃完啦..."); 11 } 12 }
1 public class Producer { 2 3 public void manufacture() { 4 System.out.println("开始制作煎饼果子..."); 5 try { 6 Thread.sleep(1000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 System.out.println("煎饼果子制作完成..."); 11 } 12 }
1 public class JoinTest { 2 3 public static void main(String[] args) { 4 Thread producerThread = new Thread(() -> { 5 Producer producer = new Producer(); 6 producer.manufacture(); 7 }); 8 producerThread.start(); 9 10 Thread consumerThread = new Thread(() -> { 11 try { 12 producerThread.join(); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 Consumer consumer = new Consumer(); 17 consumer.eat(); 18 }); 19 consumerThread.start(); 20 } 21 }
总结:
1、方法调用:sleep()、yieId()都是Thread类的静态方法;join()是Thread类的示例方法;wait()、notify()、notifyAll()是Object类的示例方法
2、释放锁:Thread.sleep()、Thread.yieId()不会释放锁;wait()会释放锁
3、执行位置:sleep()、yieId()、join()不一定需要在synchronize块中执行;wait()、notify()、notifyAll()需要在synchronize块中执行,否则会抛出IllegalMonitorStateException