欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

白话 Java Condition

程序员文章站 2024-02-17 21:49:40
...

Condition 依赖于Lock,相当于共享单车上面锁的二维码,他维护了一个或多个

像LinkedBlockingQueue的生产者和消费者一样的队列 并发库中的BlockingQueue是一个比较好玩的类,顾名思义,就是阻塞队列。该类主要提供了两个方法put()和take(),前者将一个对象放到队列中,如果队列已经满了,就等待直到有空闲节点;后者从head取一个对象,如果没有对象,就等待直到有可取的对象,

也可以叫做Lock条件,相当于三个人去骑一辆共享单车,三个人排成一个同步队列,然后第一个扫码,发现没交押金,就在旁边等,相当于unlock了,但是他放在等待队列里了,如果这时候,第二个人扫码发现也没交押金,释放锁对象unlock,他就去等待队列排队,这时候第一个人充值成功了,他就被唤醒,signal() ,他直接去扫码,扫码成功骑车走了!!!这里的是否交押金可以当做一个条件!!

package com.wangji.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyConditon {

     final static Lock lock=new ReentrantLock();
     final static Condition condition=lock.newCondition();//监视器上面维护一个等待队列,唤醒条件就是你是否充钱了
      static boolean isopen=false;

public static void main(String[] args) { 
 //线程类,相当于人,给他分配个任务 ,就是去骑车扫码
    
 class People implements Runnable{
    private String id;
    private boolean isyajin;//是否交押金
 
    
    public People(String id,boolean isyajin) {
        // TODO Auto-generated constructor stub
        this.id=id;
        this.isyajin=isyajin;
    }
    
    
    public String getId() {
        return id;
    }


    public void setId(String id) {
        this.id = id;
    }


    public boolean isIsyajin() {
        return isyajin;
    }


    public void setIsyajin(boolean isyajin) {
        this.isyajin = isyajin;
    }
 

    @Override
    public void run() {
        // TODO Auto-generated method stub
        if(isopen){
            System.out.println("已经被骑走了!老铁");
        }else{
            System.out.println("试着去开锁"+id);
            lock.lock();
            if(isyajin){
                System.out.println("我开车走了,bye!"+id);
                isopen=true;
                lock.unlock();
            }else{
                //没交押金去旁边排队
                try {
                    System.out.println("没交押金,等待"+id);
                    condition.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }finally{
                    System.out.println("排队去,未交押金"+id);
                    lock.unlock();
                }
             
            }
        } 
    }
    //人还有一个交押金的动作
    public void Yajin(){
        System.out.println("我去交押金"+id);
        this.setIsyajin(true);
        lock.lock();
        //交完押金,可以去扫码了
        condition.signalAll();
        lock.unlock();
    }
     
} 
    
   //用线程池进行处理,相当于摩拜单车后台
   ExecutorService service=Executors.newFixedThreadPool(3);
   
   //二个人
    People p1=  new People("1", false);
    People p2=  new People("2", false);
    //开锁
   service.execute(p1);
   if(!p1.isIsyajin()&&!isopen){
       p1.Yajin();
   }
   
   service.execute(p2);
 
   if(!p2.isIsyajin()&&!isopen){
       p2.Yajin();
   }
    
   //执行 
   service.shutdown();

}
}
也可以维护多个等待队列,相当于条件判断

package com.wangji.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionTs {
public static void main(String[] args) {
// 创建并发访问的账户
MyCount myCount = new MyCount("95599200901215522", 10000);
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(3); //#假设改成2会怎么样??
Thread t1 = new SaveThread("张三", myCount, 1000);
Thread t2 = new SaveThread("李四", myCount, 1000);
Thread t3 = new DrawThread("王五", myCount, 12600);
Thread t4 = new SaveThread("老张", myCount, 600);
Thread t5 = new DrawThread("老牛", myCount, 1300);
Thread t6 = new DrawThread("胖子", myCount, 800);
Thread t7 = new SaveThread("测试", myCount, 2100);
// 执行各个线程
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
pool.execute(t7);
// 关闭线程池
pool.shutdown();
}
}

/**

  • 存款线程类
    */
    class SaveThread extends Thread {
    private String name; // 操作人
    private MyCount myCount; // 账户
    private int x; // 存款金额

    SaveThread(String name, MyCount myCount, int x) {
    this.name = name;
    this.myCount = myCount;
    this.x = x;
    }

    public void run() {
    myCount.saving(x, name);
    }
    }

/**

  • 取款线程类
    */
    class DrawThread extends Thread {
    private String name; // 操作人
    private MyCount myCount; // 账户
    private int x; // 存款金额

    DrawThread(String name, MyCount myCount, int x) {
    this.name = name;
    this.myCount = myCount;
    this.x = x;
    }

    public void run() {
    myCount.drawing(x, name);
    }
    }

/**

  • 普通银行账户,不可透支
    */
    class MyCount {
    private String oid; // 账号
    private int cash; // 账户余额
    private Lock lock = new ReentrantLock(); // 账户锁
    private Condition _save = lock.newCondition(); // 存款条件
    private Condition _draw = lock.newCondition(); // 取款条件

    MyCount(String oid, int cash) {
    this.oid = oid;
    this.cash = cash;
    }

    /**

    • 存款
    • @param x
    •        操作金额
      
    • @param name
    •        操作人
      

    */
    public void saving(int x, String name) {
    lock.lock(); // 获取锁
    if (x > 0) {
    cash += x; // 存款
    System.out.println(name + "存款" + x + ",当前余额为" + cash);
    }
    _draw.signalAll(); // 唤醒所有等待线程。
    lock.unlock(); // 释放锁
    }

    /**

    • 取款
    • @param x
    •        操作金额
      
    • @param name
    •        操作人
      

    */
    public void drawing(int x, String name) {
    lock.lock(); // 获取锁
    try {
    while (cash - x < 0) {
    _draw.await(); // 阻塞取款操作, await之后就隐示自动释放了lock,直到被唤醒自动获取

             System.out.println(name + "阻塞中");
         }
         {
             cash -= x; // 取款
             System.out.println(name + "取款" + x + ",当前余额为" + cash);
         }
         _save.signalAll(); // 唤醒所有存款操作
     } catch (InterruptedException e) {
         e.printStackTrace();
     } finally {
         lock.unlock(); // 释放锁
     }
    

    }
    }