关于线程通信

Posted juzhuxiaozhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于线程通信相关的知识,希望对你有一定的参考价值。

线程通信

1.基于synchronized

  • void wait()
    在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。

  • void notify()
    唤醒(队头)在此对象监视器上等待的单个线程。

  • void notifyAll()
    唤醒在此对象监视器上等待的所有线程。

标记位:
如果已存在的属性无法满足需求,通常在锁对象中增加标记位属性,为了实现线程的控制。
如果是两个线程:boolean。
如果是多个线程:int 1,2,3。

2.基于Lock

若使用lock,则程序中没有隐式同步监视器,也就不能使用上面三个方法进行通信。需要从显式锁上得到控制器Condition,在利用condition的三个方法进行条件控制:(原理同上)

  • await()
  • signal()
  • signalAll()

3.案例

package myCorrespond;
/**
 * Account1用于演示进程通信
 * 通过wait与Notify控制
 * wait:阻塞并放弃监视器
 *
 *Account2通过condition保证同步
 * 需要显式定义锁对象,从锁对象上获取同步条件
 * 注:
 * 1.因为显式定义锁,所以不能使用wait与notify
 * 2.需要显示关锁
 */

import java.util.Objects;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Account1 {
    private String accountNo;
    private double balance;
    //标志账户中是否已有存款
    private boolean f=false;

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

    public String getAccountNo() {
        return accountNo;
    }

    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }

    public double getBalance() {
        return balance;
    }
    public synchronized void draw(double drawAmount)  {
        try{
            if(!f){//没有存款
                wait();
            }
            else{
                //取钱
                System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);
                balance-=drawAmount;
                System.out.println("余额:"+balance);
                f=false;
                notifyAll();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
    public synchronized void deposit(double depositAmount){
        try{
            if(f){
                wait();
            }
            else {
                System.out.println(Thread.currentThread().getName()+" 存款:"+depositAmount);
                balance+=depositAmount;
                System.out.println("余额:"+balance);
                f=true;
                notifyAll();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Account1 account = (Account1) o;
        return Objects.equals(accountNo, account.accountNo);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accountNo);
    }
}

class Account2{
    //显式定义锁对象
    private final Lock lock=new ReentrantLock();
    //从锁对象上拿到控制条件
    private final Condition condition=lock.newCondition();
    private String accountNo;
    private double balance;
    //标志账户中是否已有存款
    private boolean f=false;
    public Account2(String accountNo, double balance) {
        this.accountNo = accountNo;
        this.balance = balance;
    }

    public String getAccountNo() {
        return accountNo;
    }

    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }

    public double getBalance() {
        return balance;
    }
    public void draw(double drawAmount)  {
        //加锁
        lock.lock();
        try{
            if(!f){//m欸有存款
                condition.await();
            }
            else{
                //取钱
                System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);
                balance-=drawAmount;
                System.out.println("余额:"+balance);
                f=false;
                condition.signalAll();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally{
            lock.unlock();
        }
    }
    public void deposit(double depositAmount){
        lock.lock();
        try{
            if(f){
                condition.await();
            }
            else {
                System.out.println(Thread.currentThread().getName()+" 存款:"+depositAmount);
                balance+=depositAmount;
                System.out.println("余额:"+balance);
                f=true;
                condition.signalAll();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Account2 account = (Account2) o;
        return Objects.equals(accountNo, account.accountNo);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accountNo);
    }

}


class DrawThread extends Thread {
    private Account2 account;
    private double drawAmount;

    public DrawThread(String name,Account2 account,double drawAmount){
        super(name);
        this.account=account;
        this.drawAmount=drawAmount;
    }

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

class depositThread extends Thread{
    private Account2 account;
    private double depositAmount;

    public depositThread(String name,Account2 account,double depositAmount){
        super(name);
        this.account=account;
        this.depositAmount=depositAmount;
    }

    @Override
    public void run(){
        for(int i=0;i<100;i++){
            account.deposit(depositAmount );
        }
    }
}
public class AccountMode{
    public static void main(String[] args) {
        Account2 account = new Account2("myaccount", 0);
        new DrawThread("取钱者",account,800).start();
        new depositThread("存钱者甲",account,800).start();
        new depositThread("存钱者已",account,800).start();
        new depositThread("存钱者丙",account,800).start();
    }

}

以上是关于关于线程通信的主要内容,如果未能解决你的问题,请参考以下文章

关于线程通信

20160227.CCPP体系详解(0037天)

Motan在服务provider端用于处理request的线程池

在tablayout片段之间进行通信[重复]

多线程二(线程通信)

关于线程之间的通信和同步