线程通信
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();
}
}