举个小栗子,重新理解一下synchronized,volatile,wait(),notify(),join()

tech2024-05-09  83

 

直接步入正题:

1、若有一个方法需要实现多线程情况下一个一个访问,则可使用synchronized关键字来实现。 2、若有一个工作是需要用两个或多个线程来共同协作完成,并且必须是完成某个动作之后才能执行下一个动作,则可使用 wait() 和 notify() 结合来操作,也可使用volatile关键字来实现 ,也可以使用join()来实现。

举个栗子:

/** * @author HMM * */ public class TestWait { String name = "QQQ";//随意 volatile boolean flag = false;// volatile 关键字使flag线程之间可见 /** * 使用synchronized来完成排队吃饭的动作 * 一个一个排队吃饭饭呦 */ public synchronized void eat() { System.out.println("当前线程ID:" + Thread.currentThread().getId() + ",在吃饭,等会吧"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程ID:" + Thread.currentThread().getId() + ",吃完了,下一位"); System.out.println("===============================================\n"); } /** * 方式1 * 使用wait 和 notify 来实现先下载图片再展示图片动作 */ public void downAndShow() { // 开启一个线程专门下载图片 new Thread(new Runnable() { public void run() { downLoad(); } }).start(); // 开启一个线程专门显示图片 new Thread(new Runnable() { public void run() { show(); } }).start(); } public void downLoad() { System.out.println("开始下载图片"); for (int i = 0; i < 101; i += 10) { System.out.println("down" + i + "%"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (name) { name.notify(); } System.out.println("图片下载成功"); } public void show() { synchronized (name) { try { name.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("展示图片"); } } /** * 方式2 * 使用 volatile 关键字 */ public void volatileDownAndShow() { // 开启一个线程专门下载图片 new Thread(new Runnable() { public void run() { volatileDownLoad(); } }).start(); // 开启一个线程专门显示图片 new Thread(new Runnable() { public void run() { volatileShow(); } }).start(); } public void volatileDownLoad() { System.out.println("开始下载图片"); for (int i = 0; i < 101; i += 10) { System.out.println("down" + i + "%"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } flag = true;//设置flag为true,表示我已经把图片下载好了,剩下的交给你了兄弟 System.out.println("图片下载成功"); } public void volatileShow() { while (true) {//死循环,模拟自旋锁 if(flag){//因为flag 为volatile 所以在线程之间可见,线程1改变后,线程2也会随之改变 System.out.println("展示图片"); break; } } } /** * 方式3 * join() * @throws InterruptedException * */ public void JoinDownAndShow() throws InterruptedException { // 开启一个线程专门下载图片 Thread thread1 = new Thread(new Runnable() { public void run() { JoinDownLoad(); } }); // 开启一个线程专门显示图片 Thread thread2 = new Thread(new Runnable() { public void run() { JoinShow(); } }); thread1.start(); thread1.join();// thread1调用join()方法,等到thread1执行完毕之后才执行下面操作 thread2.start(); } public void JoinDownLoad() { System.out.println("join() 方式 开始下载图片"); for (int i = 0; i < 101; i += 10) { System.out.println("down" + i + "%"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("图片下载成功"); } public void JoinShow() { System.out.println("展示图片"); } }

编写测试类:

public class Test { public static void main(String[] args) { final TestWait tt = new TestWait(); //开始10个线程来模拟排队吃饭 // for(int i=0;i<10;i++){ // new Thread(new Runnable() { // public void run() { // tt.eat(); // } // }).start();; // } // tt.downAndShow(); // tt.volatileDownAndShow(); tt.JoinDownAndShow(); } }

结果展示:

1、排队吃饭示例:

2、wait() 和 notify() 实现下载图片后展示:

3、volatile方式实现下载图片后展示:

就酱。共勉

最新回复(0)