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

 

 

 

 

 

 

 

 

 

posted @ 2014-06-18 23:36  廖凯林  阅读(561)  评论(0编辑  收藏  举报