线程通信
线程通信有三种方法:一是利用Obeject的wait,notify,notifyAll。二是利用condition配合lock。三是利用BlockingQueue接口,put方法,take方法。
方法一:
class Account { private String accountNo; private double balance; private boolean flag = false; public Account(){} public Account(String accountNo, double balance) { this.setAccountNo(accountNo); this.setBalance(balance); } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public synchronized void draw(double drawAmount) { try { if(!flag) { wait(); } else { System.out.println(Thread.currentThread().getName()+"取钱:" + drawAmount); balance -= drawAmount; System.out.println(Thread.currentThread().getName()+"取钱成功!吐出钞票:"+drawAmount); flag = false; notifyAll(); } } catch(InterruptedException ex) { ex.printStackTrace(); } } public synchronized void deposit(double depositeAmount) { try { if(flag) { wait(); } else { System.out.println(Thread.currentThread().getName()+"存款:"+depositeAmount); balance += depositeAmount; System.out.println("账户余额为:"+ balance); flag = true; notifyAll(); } } catch(InterruptedException ex) { ex.printStackTrace(); } } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } } class DepositThread extends Thread { private Account account; private double depositAmount; public DepositThread(String name, Account account, double drawAmount) { super(name); this.account = account; this.depositAmount = drawAmount; } public void run() { for(int i = 0; i < 100; i ++) { account.deposit(depositAmount); } } } class DrawTest { public static void main(String[] args) { Account acct = new Account("1213", 0); new DrawThread("取钱者", acct, 800).start(); new DepositThread("存钱者甲", acct, 800).start(); } } public class DrawThread extends Thread { private Account account; private double drawAmount; public DrawThread(String name, Account account, double drawAmount) { super(name); this.account = account; this.drawAmount = drawAmount; } public void run() { for(int i = 0; i < 100; i ++) { account.draw(drawAmount); } } }
方法二:由于Clock没有隐式的同步监视器,所有要借助Condition
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Account2 { //使用lock,没有隐式同步监视器,需要使用condition private final Lock lock = new ReentrantLock(); private final Condition cond = lock.newCondition(); private String accountNo; private double balance; private boolean flag = false; public Account2(){} public Account2(String accountNo, double balance) { this.setAccountNo(accountNo); this.setBalance(balance); } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public void draw(double drawAmount) { lock.lock(); try { if(!flag) { cond.await(); } else { System.out.println(Thread.currentThread().getName()+"取钱:" + drawAmount); balance -= drawAmount; System.out.println(Thread.currentThread().getName()+"取钱成功!吐出钞票:"+drawAmount); flag = false; cond.signalAll(); } } catch(InterruptedException ex) { ex.printStackTrace(); } } public synchronized void deposit(double depositeAmount) { try { if(flag) { cond.await(); } else { System.out.println(Thread.currentThread().getName()+"存款:"+depositeAmount); balance += depositeAmount; System.out.println("账户余额为:"+ balance); flag = true; cond.signalAll(); } } catch(InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); } } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } }
方法三:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueTest { public static void main(String[] args) { BlockingQueue<String> bq = new ArrayBlockingQueue<>(1); new Producer(bq).start(); new Producer(bq).start(); new Producer(bq).start(); new Consumer(bq).start(); } } class Producer extends Thread { BlockingQueue<String> bq; public Producer(BlockingQueue<String> bq) { this.bq = bq; } public void run() { String[] strArr = {"java", "c", "python"}; for(int i = 0; i < 100; i ++) { try { Thread.sleep(200); bq.put(strArr[i%3]); } catch(InterruptedException ex) { ex.printStackTrace(); } System.out.println(getName()+"生产者生产元素:"+bq); } } } class Consumer extends Thread { BlockingQueue<String> bq; public Consumer(BlockingQueue<String> bq) { this.bq = bq; } public void run() { while(true) { try { Thread.sleep(200); bq.take(); } catch(InterruptedException ex) { ex.printStackTrace(); } System.out.println(getName()+"消费者消费完毕。"); } } }