Java多线程--线程通信使用案例

线程通信
wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()方法和notifyAll()方法来唤醒该线程
notify():唤醒在此同步监视器上等待的单个线程,会选择唤醒其中的任意一个线程,选择是任意的。只有当前线程放弃对该同步监视器的锁定后(调用wait()方法),才会执行被唤醒的线程。
notifyAll():唤醒在此同步监视器上等待的所有线程。只有放弃对该同步监视器的锁定后才可以执行被唤醒的线程。
采用Object中的方法模拟存取取钱的操作。只有当存钱后才执行取钱操作。
账户类:

public class Account {

	private String accountNo;

	private double balance;

	/**
	 * 是否存钱标示
	 */
	private boolean flag = false;

	public Account(String accountNo, double balance) {
		this.accountNo = accountNo;
		this.balance = balance;
	}

	/**
	 * 取钱
	 * 
	 * @param drawAmount
	 */
	public synchronized void draw(double drawAmount) {
		try {
			if (this.flag) {
				System.out.println("开始取钱:" + drawAmount);
				this.balance -= drawAmount;
				this.flag = false;
				notifyAll();
			} else {
				System.out.println("当前无钱,");
				wait();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 存钱
	 * 
	 * @param depositAmount
	 */
	public synchronized void deposit(double depositAmount) {
		try {
			if (!this.flag) {
				System.out.println("开始存钱" + depositAmount);
				this.balance += depositAmount;
				this.flag = true;
				notifyAll();
			} else {
				System.out.println("当前已存钱");
				wait();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

存钱线程:

public class DepositThread implements Runnable {

	private Account account;

	private Integer depositAmount;

	public DepositThread(Account account, Integer depositAmount) {
		this.account = account;
		this.depositAmount = depositAmount;
	}

	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			account.deposit(this.depositAmount);
		}
	}
}

取钱线程:

public class DrawThread implements Runnable {

	private Account account;

	private Integer drawAmount;

	public DrawThread(Account account, Integer drawAmount) {
		this.account = account;
		this.drawAmount = drawAmount;
	}

	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			account.draw(this.drawAmount);
		}
	}
}

启动:

public class TestMain {

	public static void main(String[] args) {
		Account account = new Account("123456", 0);

		new Thread(new DepositThread(account, 800), "存钱者").start();

		new Thread(new DrawThread(account, 800), "取钱者").start();
	}
}

当执行存钱操作,增加该账户的余额,将是否存钱标示符改为true,同时唤醒该同步锁上的其他线程,存钱操作再次执行,则该线程进入睡眠状态,取钱线程开始执行,减少余额,将是否存钱标示符该为false,唤醒该同步锁上的其他资源。
简化版

    @Test
    public void test13() throws InterruptedException {
        Object obj=new Object();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (obj){
                    System.out.println("t1 获取到锁");
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1 再次获取到锁");
                }
            }
        }).start();

        Thread.sleep(100);
        synchronized (obj){
            System.out.println("main 获取到锁");
            Thread.sleep(10000);
            obj.notify();
        }
        while (Thread.activeCount()>2){}
        System.out.println("run over");
    }

使用LockSupport

    /**
     * LockSupport使用
     */
    @Test
    public void test02(){
        Thread t01=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("开始阻塞");
                LockSupport.park();
                System.out.println("阻塞结束");
            }
        });
        t01.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("解除t01的阻塞");
        LockSupport.unpark(t01);
        while (Thread.activeCount()>2){}
        System.out.println("run over");
    }

LockSupport使用案例二

		Thread t01 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("开始等待");
				long beginTime = System.currentTimeMillis();
				//停顿10秒
				long waitTime=TimeUnit.NANOSECONDS.convert(10, TimeUnit.SECONDS);
				LockSupport.parkNanos(waitTime);
				System.out.println("等待结束:"+(System.currentTimeMillis()-beginTime));
			}
		});
		t01.start();
		
		Thread.sleep(2000);
		System.out.println("开始唤醒");
		LockSupport.unpark(t01);
		while(Thread.activeCount()>2) {}
    @Test
    public void test03() throws InterruptedException {
        Object obj=new Object();
        Thread t01=new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (obj){
                    System.out.println("开始阻塞");
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("结束阻塞");
                }
            }
        });
        t01.start();

        Thread.sleep(2000);
        synchronized (obj){
            System.out.println("唤醒obj上的线程");
            obj.notify();
        }
        while (Thread.activeCount()>2){}
        System.out.println("run over");
    }

使用案例-两个线程交替执行

@Test
	public void test04() {
		Object obj01 = new Object();

		Thread t01 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					synchronized (obj01) {
						try {
							Thread.sleep(1000);

							System.out.println(1);
							obj01.notify();
							obj01.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		});
		t01.start();

		Thread t02 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					synchronized (obj01) {
						try {
							Thread.sleep(1000);
							System.out.println(2);
							obj01.notify();

							obj01.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		});
		t02.start();

		while (Thread.activeCount() > 2) {
		}
		System.out.println("run over");
	}

进阶-三个线程交替执行

        Object obj01 = new Object();

        Object obj02 = new Object();

        Object obj03 = new Object();

        Thread t01 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (obj01) {
                        try {
                            Thread.sleep(1000);

                            System.out.print(1);

                            synchronized (obj02) {
                                obj02.notify();
                            }
                            obj01.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        t01.start();
        //让第一个线程先跑起来
        Thread.sleep(1000);

        Thread t02 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (obj02) {
                        try {
                            Thread.sleep(1000);
                            System.out.print(2);

                            synchronized (obj03) {
                                obj03.notify();
                            }

                            obj02.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        t02.start();

        //让第二个线程执行起来
        Thread.sleep(1000);

        Thread t03 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (obj03) {
                        try {
                            Thread.sleep(1000);
                            System.out.println(3);

                            synchronized (obj01) {
                                obj01.notify();
                            }

                            obj03.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        t03.start();

        while (Thread.activeCount() > 2) {
        }
        System.out.println("run over");

参考https://www.cnblogs.com/qingquanzi/p/8228422.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值