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


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

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

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

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

    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

    取钱线程

    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

    存钱线程

    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

    测试类

    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
    学习的时间不一定要特定安排
  • 相关阅读:
    Nginx和PHP-FPM的启动、重启、停止脚本分享
    [Linux]Fedora19修复被Windows干掉的引导
    [Linux]RHEL/CentOS6配置tomcat使用80端口(与httpd整合)
    [Linux]SAMBA共享打印机
    [Linux]配置Logwatch使用第三方smtp发送电子邮件
    [oVirt]在双网卡网络环境下使用oVirt LiveCD
    走进Linux世界主题讲座纪录
    mysql用户及权限复制
    记一次失败的K8S安装部署
    HTTP状态码与爬虫
  • 原文地址:https://www.cnblogs.com/zhongzheng123/p/8036516.html
Copyright © 2020-2023  润新知