zoukankan      html  css  js  c++  java
  • Java多线程之Lock的使用

    http://blog.csdn.net/huang_xw/article/details/7090177
    [java] view plain copy
     
     print?
    1. import java.util.concurrent.ExecutorService;  
    2. import java.util.concurrent.Executors;  
    3. import java.util.concurrent.Future;  
    4. import java.util.concurrent.locks.Lock;  
    5. import java.util.concurrent.locks.ReadWriteLock;  
    6. import java.util.concurrent.locks.ReentrantLock;  
    7. import java.util.concurrent.locks.ReentrantReadWriteLock;  
    8.   
    9. /** 
    10.  * Lockers 
    11.  * 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性, 
    12.  * 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作, 
    13.  * 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。 
    14.  */  
    15. public class Lockers {  
    16.       
    17.     /** 
    18.      * 测试Lock的使用。在方法中使用Lock,可以避免使用Synchronized关键字。 
    19.      */  
    20.     public static class LockTest {  
    21.   
    22.         Lock lock = new ReentrantLock();// 锁  
    23.         double value = 0d; // 值  
    24.         int addtimes = 0;  
    25.   
    26.         /** 
    27.          * 增加value的值,该方法的操作分为2步,而且相互依赖,必须实现在一个事务中 
    28.          * 所以该方法必须同步,以前的做法是在方法声明中使用Synchronized关键字。 
    29.          */  
    30.         public void addValue(double v) {  
    31.             lock.lock();// 取得锁  
    32.             System.out.println("LockTest to addValue: " + v + "   "  
    33.                     + System.currentTimeMillis());  
    34.             try {  
    35.                 Thread.sleep(1000);  
    36.             } catch (InterruptedException e) {  
    37.             }  
    38.             this.value += v;  
    39.             this.addtimes++;  
    40.             lock.unlock();// 释放锁  
    41.         }  
    42.   
    43.         public double getValue() {  
    44.             return this.value;  
    45.         }  
    46.     }  
    47.     public static void testLockTest() throws Exception{  
    48.         final LockTest lockTest = new LockTest();  
    49.         // 新建任务1,调用lockTest的addValue方法  
    50.         Runnable task1 = new Runnable(){  
    51.             public void run(){  
    52.                 lockTest.addValue(55.55);  
    53.             }  
    54.         };  
    55.         // 新建任务2,调用lockTest的getValue方法  
    56.         Runnable task2 = new Runnable(){  
    57.             public void run(){  
    58.                 System.out.println("value: " + lockTest.getValue());  
    59.             }  
    60.         };  
    61.         // 新建任务执行服务  
    62.         ExecutorService cachedService = Executors.newCachedThreadPool();  
    63.         Future future = null;  
    64.         // 同时执行任务1三次,由于addValue方法使用了锁机制,所以,实质上会顺序执行  
    65.         for (int i=0; i<3; i++){  
    66.             future = cachedService.submit(task1);  
    67.         }  
    68.         // 等待最后一个任务1被执行完  
    69.         future.get();  
    70.         // 再执行任务2,输出结果  
    71.         future = cachedService.submit(task2);  
    72.         // 等待任务2执行完后,关闭任务执行服务  
    73.         future.get();  
    74.         cachedService.shutdownNow();  
    75.     }  
    76.       
    77.     /** 
    78.      * ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。 
    79.      * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock, 
    80.      * 而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有: 
    81.      * readLock(): 返回一个读的lock  
    82.      * writeLock(): 返回一个写的lock, 此lock是排他的。 
    83.      * ReadWriteLockTest很适合处理类似文件的读写操作。 
    84.      * 读的时候可以同时读,但不能写;写的时候既不能同时写也不能读。 
    85.      */  
    86.     public static class ReadWriteLockTest{  
    87.         // 锁  
    88.         ReadWriteLock lock = new ReentrantReadWriteLock();  
    89.         // 值  
    90.         double value = 0d;  
    91.         int addtimes = 0;  
    92.           
    93.         /** 
    94.          * 增加value的值,不允许多个线程同时进入该方法 
    95.          */  
    96.         public void addValue(double v) {  
    97.             // 得到writeLock并锁定  
    98.             Lock writeLock = lock.writeLock();  
    99.             writeLock.lock();  
    100.             System.out.println("ReadWriteLockTest to addValue: " + v + "   "  
    101.                     + System.currentTimeMillis());  
    102.             try {  
    103.                 Thread.sleep(1000);  
    104.             } catch (InterruptedException e) {  
    105.             }  
    106.             try {  
    107.                 // 做写的工作  
    108.                 this.value += v;  
    109.                 this.addtimes++;  
    110.             } finally {  
    111.                 // 释放writeLock锁  
    112.                 writeLock.unlock();  
    113.             }  
    114.         }  
    115.         /** 
    116.          * 获得信息。当有线程在调用addValue方法时,getInfo得到的信息可能是不正确的。 
    117.          * 所以,也必须保证该方法在被调用时,没有方法在调用addValue方法。 
    118.          */  
    119.         public String getInfo() {  
    120.             // 得到readLock并锁定  
    121.             Lock readLock = lock.readLock();  
    122.             readLock.lock();  
    123.             System.out.println("ReadWriteLockTest to getInfo   "  
    124.                     + System.currentTimeMillis());  
    125.             try {  
    126.                 Thread.sleep(1000);  
    127.             } catch (InterruptedException e) {  
    128.             }  
    129.             try {  
    130.                 // 做读的工作  
    131.                 return this.value + " : " + this.addtimes;  
    132.             } finally {  
    133.                 // 释放readLock  
    134.                 readLock.unlock();  
    135.             }  
    136.         }  
    137.     }  
    138.       
    139.     public static void testReadWriteLockTest() throws Exception{  
    140.         final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();  
    141.         // 新建任务1,调用lockTest的addValue方法  
    142.         Runnable task_1 = new Runnable(){  
    143.             public void run(){  
    144.                 readWriteLockTest.addValue(55.55);  
    145.             }  
    146.         };  
    147.         // 新建任务2,调用lockTest的getValue方法  
    148.         Runnable task_2 = new Runnable(){  
    149.             public void run(){  
    150.                 System.out.println("info: " + readWriteLockTest.getInfo());  
    151.             }  
    152.         };  
    153.         // 新建任务执行服务  
    154.         ExecutorService cachedService_1 = Executors.newCachedThreadPool();  
    155.         Future future_1 = null;  
    156.         // 同时执行5个任务,其中前2个任务是task_1,后两个任务是task_2  
    157.         for (int i=0; i<2; i++){  
    158.             future_1 = cachedService_1.submit(task_1);  
    159.         }  
    160.         for (int i=0; i<2; i++){  
    161.             future_1 = cachedService_1.submit(task_2);  
    162.         }  
    163.         // 最后一个任务是task_1  
    164.         future_1 = cachedService_1.submit(task_1);  
    165.         // 这5个任务的执行顺序应该是:  
    166.         // 第一个task_1先执行,第二个task_1再执行;这是因为不能同时写,所以必须等。  
    167.         // 然后2个task_2同时执行;这是因为在写的时候,就不能读,所以都等待写结束,  
    168.         // 又因为可以同时读,所以它们同时执行  
    169.         // 最后一个task_1再执行。这是因为在读的时候,也不能写,所以必须等待读结束后,才能写。  
    170.           
    171.         // 等待最后一个task_2被执行完  
    172.         future_1.get();  
    173.         cachedService_1.shutdownNow();  
    174.     }  
    175.   
    176.     public static void main(String[] args) throws Exception{  
    177.         Lockers.testLockTest();  
    178.         System.out.println("---------------------");  
    179.         Lockers.testReadWriteLockTest();  
    180.     }  
    181. }  
     
    5
  • 相关阅读:
    Kafka与RabbitMQ区别
    Illegal instruction 问题的解决方法
    Debian 6 , 十个串口为什么只识别到了 6个 剩下4 个被禁止了
    微信二次认证 C#
    修改XtraMessageBox的内容字体大小
    svn: E155017: Checksum mismatch while updating 校验错误的解决方法
    再生龙恢复分区后修复引导或debian linux修复引导 三部曲
    Clonezilla制作镜像时报错: errextfsclone.c:bitmap free count err
    我用windows live Writer 写个日志试试看
    Debian下签名无法验证
  • 原文地址:https://www.cnblogs.com/ruiati/p/6125450.html
Copyright © 2011-2022 走看看