zoukankan      html  css  js  c++  java
  • 多线程09-Lock和Condition

    1.概念

        Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。

    2.案例

    package org.lkl.thread;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockFoo {
        /**
         * 两个线程打印姓名
         */
        
        
        public static void main(String[] args) {
            final Outputter out = new Outputter() ;
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                     while(true){
                         try {
                            Thread.sleep(200) ;
                            out.print("zhangsan") ;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                     }
                }
            }).start();
            
            
            new Thread(new Runnable() {
                        
                        @Override
                        public void run() {
                             while(true){
                                 try {
                                    Thread.sleep(1000) ;
                                    out.print("liaokailinliaokailinliaokailinliaokailinliaokailinliaokailin") ;
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                             }
                        }
                    }).start();
        }
        
        
        
    }
    
    
    class Outputter{
        Lock lock = new ReentrantLock() ;
        public void print(String name){
            lock.lock() ; //加上锁  只有等到操作全完成以后才释放锁
            try {
                if(name!=null){
                    for(int i = 0 ; i<name.length() ;i++){
                        System.out.print(name.charAt(i));
                    }
                    System.out.println();
                }
            }finally {
                lock.unlock() ;//解锁 一般都在finally中解锁  不过程序是否有异常 最终都要解锁 否则会导致阻塞
            }
        }
    }

        

    3. 读写锁

         读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;

    如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

    package cn.itcast.heima2;
    
    import java.util.Random;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class ReadWriteLockTest {
        public static void main(String[] args) {
            final Queue3 q3 = new Queue3();
            for(int i=0;i<3;i++)
            {
                new Thread(){
                    public void run(){
                        while(true){
                            q3.get();                        
                        }
                    }
                    
                }.start();
    
                new Thread(){
                    public void run(){
                        while(true){
                            q3.put(new Random().nextInt(10000));
                        }
                    }            
                    
                }.start();
            }
            
        }
    }
    
    class Queue3{
        private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
        ReadWriteLock rwl = new ReentrantReadWriteLock();
        public void get(){
            rwl.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() + " be ready to read data!");
                Thread.sleep((long)(Math.random()*1000));
                System.out.println(Thread.currentThread().getName() + "have read data :" + data);            
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                rwl.readLock().unlock();
            }
        }
        
        public void put(Object data){
    
            rwl.writeLock().lock();
            try {
                System.out.println(Thread.currentThread().getName() + " be ready to write data!");                    
                Thread.sleep((long)(Math.random()*1000));
                this.data = data;        
                System.out.println(Thread.currentThread().getName() + " have write data: " + data);                    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                rwl.writeLock().unlock();
            }
            
        
        }
    }

    4. Condition

    package org.lkl.thead.foo01;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ConditionFoo {
        /**
         * 子线程先执行10次 然后主线程再执行20次 如此循环50次
         */
        public static void main(String[] args) {
        final Business b = new Business() ;
            //子线程执行50次
            for(int i = 1 ;i<=50 ;i++){
                final int seq = i ;
                new Thread(new Runnable() {
                    
                    public void run() {
                        b.sub(seq) ;
                    }
                }).start() ;
            }
            
            //主线程执行50次
            for(int i = 1 ;i<=50 ;i++){
                   b.main(i) ;         
            }
            
        }
        
        
    }
    
    class Business{
        boolean isSub =  true ;
        
        Lock lock = new ReentrantLock() ;
        Condition condition = lock.newCondition() ;
        //子线程执行10次
        public  void sub(int j ){  //加lock以后不需要synchronized
            lock.lock() ;
            try {
                while(!isSub){
                    try {
                        condition.await() ;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for(int i = 1 ;i<=10 ;i++){
                    System.out.println("sub thread execute times " + i  + " loop of "+ j);
                }
                
                isSub = false ;
                condition.signalAll() ;
            } finally {
                lock.unlock() ;
            }
            
        }
        
        
        //主线程执行20次
        public  void main(int j ){
            lock.lock() ;
            try {
                while(isSub){
                    try {
                        condition.await() ;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for(int i = 1 ;i<=20 ;i++){
                    System.out.println("main thread execute times " + i  + " loop of "+ j);
                }
                
                isSub = true ;
            //    condition.signal() ;
                condition.signalAll() ;
            }finally {
                lock.unlock() ;
            }
        }
    }

     5. 通过condition实现三个线程之间的通信

    package cn.itcast.heima2;
    
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ThreeConditionCommunication {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            
            final Business business = new Business();
            new Thread(
                    new Runnable() {
                        
                        @Override
                        public void run() {
                        
                            for(int i=1;i<=50;i++){
                                business.sub2(i);
                            }
                            
                        }
                    }
            ).start();
            
            new Thread(
                    new Runnable() {
                        
                        @Override
                        public void run() {
                        
                            for(int i=1;i<=50;i++){
                                business.sub3(i);
                            }
                            
                        }
                    }
            ).start();        
            
            for(int i=1;i<=50;i++){
                business.main(i);
            }
            
        }
    
        static class Business {
                Lock lock = new ReentrantLock();
                Condition condition1 = lock.newCondition();
                Condition condition2 = lock.newCondition();
                Condition condition3 = lock.newCondition();
              private int shouldSub = 1;
              public  void sub2(int i){
                  lock.lock();
                  try{
                      while(shouldSub != 2){
                          try {
                            condition2.await();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                      }
                        for(int j=1;j<=10;j++){
                            System.out.println("sub2 thread sequence of " + j + ",loop of " + i);
                        }
                      shouldSub = 3;
                      condition3.signal();
                  }finally{
                      lock.unlock();
                  }
              }
    
              public  void sub3(int i){
                  lock.lock();
                  try{
                      while(shouldSub != 3){
                          try {
                            condition3.await();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                      }
                        for(int j=1;j<=20;j++){
                            System.out.println("sub3 thread sequence of " + j + ",loop of " + i);
                        }
                      shouldSub = 1;
                      condition1.signal();
                  }finally{
                      lock.unlock();
                  }
              }          
              
              public  void main(int i){
                  lock.lock();
                  try{
                     while(shouldSub != 1){
                              try {
                                condition1.await();
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                          }
                        for(int j=1;j<=100;j++){
                            System.out.println("main thread sequence of " + j + ",loop of " + i);
                        }
                        shouldSub = 2;
                        condition2.signal();
              }finally{
                  lock.unlock();
              }
          }
        
        }
    }
  • 相关阅读:
    linux:centos7开启指定端口,开放外网访问
    zookeeper 集群搭建
    单机安装zookeeper的3.4.7版本
    CentOS7下安装jdk1.8并配置环境变量,防火墙设置开关
    Redis分布式锁的正确实现方式
    MySQl5.7 忘记密码怎么办?
    Flink 之Window(窗口)
    Flink之Sink(文件、Kafka、Redis、Es、Mysql)
    Canal同步Mysql数据至Hbase
    Flink 之分流Select与Split
  • 原文地址:https://www.cnblogs.com/liaokailin/p/3795610.html
Copyright © 2011-2022 走看看