并发编程学习笔记(五、线程中常用的方法)

目录:

  • 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

 

猜你喜欢

转载自www.cnblogs.com/bzfsdr/p/11568253.html