• 线程通信


    线程通信有三种方法:一是利用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()+"消费者消费完毕。");
    		}
    	}
    }
    
  • 相关阅读:
    九大经典算法之插入排序、希尔排序
    1072 开学寄语 (20 分)
    1070 结绳 (25 分
    查找字符串中的所有数字
    通过类继承计算梯形面积
    将命令的输出生成一个Web页面
    从Internet下载一个文件
    使用Excel管理命令输出
    将一个命令的输出保存到CSV文件
    使用属性存储用户编号和姓名
  • 原文地址:https://www.cnblogs.com/masterlibin/p/5614773.html
Copyright © 2020-2023  润新知