java基础笔记--多线程同步与协作

时间:2023-02-16 19:53:51

  线程的同步与协作,这个概念很普通就是说,一个线程需要等另一个线程完成或者完成某部分时才能继续工作。

线程之间的同步与协作,有一个经典的场景:生产者与消费者。如库存不足,那么消费者线程需要等待,生产者生产出足够的物品。生产者和消费者都需要访问物品库,同一时刻(在某个操作下)只能有一个线程占用。 既然是线程,那么线程运行CPU时间片不怎么好控制,涉及到数据安全还需要涉及到锁。临界资源只能有一个线程占用,那么等待的线程需要释放锁,但又要保留线程当前的运算结果中间值。使用wait方法,释放线程占用的资源,进入阻塞状态,等待生产者线程唤醒,然后重新去抢占锁等其他资源就使用条件(Condition)便于线程间通信,来实现

因为缺钱,就拿取钱作为例子。

这是账户代码,取钱和存钱

java基础笔记--多线程同步与协作java基础笔记--多线程同步与协作
package com.Thread.sync;

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

public class Accout {
    private Lock lock = new ReentrantLock(true);
    private Condition newDeposit = lock.newCondition(); // 创建一个条件
    
    private int money=100;
    
    
    public void addMoney(int aum){
        lock.lock();
        try {
            
            Thread.sleep(1000);
            money=money+aum;
            newDeposit.signalAll();
            System.out.println(" 存 "+aum+" 元  现在余额共:"+money);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
        
    }
    
    /**
     *取款是一定要成功的,不成功便等待 
     * @param put
     */
    public void putMoney(int put){
        lock.lock();
        try {
            Thread.sleep(1000);
            //代表历史处理过的逻辑,
            System.out.println("取钱之前的准备工作。。。。");
            while(money<put){
                System.out.println("取出  "+put+" 元" +" 余额不足无法取出  当前余额:"+money);
                newDeposit.await();
            }
            Thread.sleep(1000);
            money=money-put;
            System.out.println("成功取出"+put+" 元 ,余额:"+money+" 元-------------");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }
    
}
View Code

取钱线程

java基础笔记--多线程同步与协作java基础笔记--多线程同步与协作
package com.Thread;

import java.util.Random;

import com.Thread.sync.Accout;

public class GetMoney implements Runnable{
    
    private Accout accout;
    
    public GetMoney(Accout accout){
        this.accout=accout;
    }
    
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        int n=10;
        
            accout.putMoney(new Random().nextInt(8000)+2000);
            
        
    }

}
View Code

存钱线程

java基础笔记--多线程同步与协作java基础笔记--多线程同步与协作
package com.Thread.sync;

import java.util.Random;

public class AddMoney implements Runnable{
    
    private Accout accout;
    
     public AddMoney(Accout accout) {
        // TODO Auto-generated constructor stub
         this.accout=accout;
    }
    @Override
    public void run() {
        int n=20;
        while(n>1){
            accout.addMoney(new Random().nextInt(2000));
            n--;
        }
        
    }

}
View Code

测试类

java基础笔记--多线程同步与协作java基础笔记--多线程同步与协作
package com.Thread.sync;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.Thread.GetMoney;

public class Sync {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Accout accout=new Accout();
        ExecutorService executor = Executors.newCachedThreadPool();  
        executor.execute(new AddMoney(accout)); 
        executor.execute(new GetMoney(accout)); 
        
        
    }

}
View Code

运行结果:

存 587 元  现在余额共:687 取钱之前的准备工作。。。。//证明线程之前的运算被保存,并没有重复运行
取出  2386 元 余额不足无法取出  当前余额:687221 元  现在余额共:908
取出  2386 元 余额不足无法取出  当前余额:9085 元  现在余额共:913
取出  2386 元 余额不足无法取出  当前余额:9131079 元  现在余额共:1992
取出  2386 元 余额不足无法取出  当前余额:19921145 元  现在余额共:3137
成功取出2386 元 ,余额:751 元-------------197 元  现在余额共:9481029 元  现在余额共:19771104 元  现在余额共:30811542 元  现在余额共:4623650 元  现在余额共:5273585 元  现在余额共:58581096 元  现在余额共:69541258 元  现在余额共:82121617 元  现在余额共:9829763 元  现在余额共:10592954 元  现在余额共:11546183 元  现在余额共:117291815 元  现在余额共:135441647 元  现在余额共:15191