1. package thread.lock;
  2.  
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. import java.util.concurrent.Future;
  6. import java.util.concurrent.locks.Lock;
  7. import java.util.concurrent.locks.ReadWriteLock;
  8. import java.util.concurrent.locks.ReentrantLock;
  9. import java.util.concurrent.locks.ReentrantReadWriteLock;
  10.  
  11. /**
  12. * Lockers 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性,
  13. * 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作,
  14. * 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。
  15. */
  16. public class Lockers {
  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 + " " + System.currentTimeMillis());
  33. try {
  34. Thread.sleep(1000);
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. this.value += v;
  39. this.addtimes++;
  40. lock.unlock();// 释放锁
  41. }
  42.  
  43. public double getValue() {
  44. return this.value;
  45. }
  46. }
  47.  
  48. public static void testLockTest() throws Exception {
  49. final LockTest lockTest = new LockTest();
  50. // 新建任务1,调用lockTest的addValue方法
  51. Runnable task1 = new Runnable() {
  52. public void run() {
  53. lockTest.addValue(55.55);
  54. }
  55. };
  56. // 新建任务2,调用lockTest的getValue方法
  57. Runnable task2 = new Runnable() {
  58. public void run() {
  59. System.out.println("value: " + lockTest.getValue());
  60. }
  61. };
  62. // 新建任务执行服务
  63. ExecutorService cachedService = Executors.newCachedThreadPool();
  64. Future future = null;
  65. // 同时执行任务1三次,由于addValue方法使用了锁机制,所以,实质上会顺序执行
  66. for (int i = 0; i < 3; i++) {
  67. future = cachedService.submit(task1);
  68. }
  69. // 等待最后一个任务1被执行完
  70. future.get();
  71. // 再执行任务2,输出结果
  72. future = cachedService.submit(task2);
  73. // 等待任务2执行完后,关闭任务执行服务
  74. future.get();
  75. cachedService.shutdownNow();
  76. }
  77.  
  78. /**
  79. * ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。
  80. * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock,
  81. * 而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有: readLock(): 返回一个读的lock
  82. * writeLock(): 返回一个写的lock, 此lock是排他的。 ReadWriteLockTest很适合处理类似文件的读写操作。
  83. * 读的时候可以同时读,但不能写;写的时候既不能同时写也不能读。
  84. */
  85. public static class ReadWriteLockTest {
  86. // 锁
  87. ReadWriteLock lock = new ReentrantReadWriteLock();
  88. // 值
  89. double value = 0d;
  90. int addtimes = 0;
  91.  
  92. /**
  93. * 增加value的值,不允许多个线程同时进入该方法
  94. */
  95. public void addValue(double v) {
  96. // 得到writeLock并锁定
  97. Lock writeLock = lock.writeLock();
  98. writeLock.lock();
  99. System.out.println("ReadWriteLockTest to addValue: " + v + " "
  100. + System.currentTimeMillis());
  101. try {
  102. Thread.sleep(1000);
  103. } catch (InterruptedException e) {
  104. }
  105. try {
  106. // 做写的工作
  107. this.value += v;
  108. this.addtimes++;
  109. } finally {
  110. // 释放writeLock锁
  111. writeLock.unlock();
  112. }
  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. }

Java多线程之Lock的使用(转)的更多相关文章

  1. Java——多线程之Lock锁

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  2. Java多线程之Lock的使用

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

  3. java多线程之Lock线程同步

    1.线程同步: package cn.itcast.heima2; import java.util.concurrent.locks.Lock; import java.util.concurren ...

  4. (转)Java多线程之Lock的使用 (待整理)

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

  5. Java多线程之Lock的使用<转>

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

  6. java多线程之Lock/Condition简介

    在java多线程中,可以使用synchronized关键字实现线程之间的同步互斥,在jdk1.5中增加的ReentrantLock也能实现同样的效果,并且功能更加强大. 比如具有嗅探锁定,多路分支通知 ...

  7. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

  8. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

  9. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

随机推荐

  1. Codeforces 432 D. Prefixes and Suffixes

    用扩展KMP做简单省力..... D. Prefixes and Suffixes time limit per test 1 second memory limit per test 256 meg ...

  2. 【LeetCode】【Python解决问题的方法】Best Time to Buy and Sell Stock II

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  3. 生活中的大数据 hadoop

    大数据和我有关吗?大数据就是大量的数据吗?只有互联网公司才有大数据吗?想盘活大数据必须买昂贵的软硬件吗?大数据怎么存储计算?大数据,这个时下最火热的互联网词语,你了解多少呢?

  4. Threejs 它可以在建立其内部房间效果可见

    Threejs 中建立可看到其内部的房间效果 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协 ...

  5. group by和order by的错误

    select  u.Col_Name from hs_user u left join ( select tuid,count(*) as 'col_sumtopic' from BBS_Topic ...

  6. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  7. 深入解析_Android的自定义布局

    前言: 这篇文章是前Firefox Android工程师(现在跳槽去Facebook了) Lucas Rocha所写,文中对Android中常用的四种自定义布局方案进行了很好地分析,并结合这四种And ...

  8. Android UI设计规则

    Android UI技巧 1.1 不该做什么 l  不要照搬你在其他平台的UI设计,应该让用户使用感觉是在真正使用一个Android软件,在你的LOGO显示和平台总体观感之间做好平衡 l  不要过度使 ...

  9. Error Code: 1318. Incorrect number of arguments for PROCEDURE company.new_procedure; expected 2, got

    1.错误叙述性说明 20:27:34 call new_procedure(20150112) Error Code: 1318. Incorrect number of arguments for ...

  10. ACM:图BFS,迷宫

    称号: 网络格迷宫n行m单位列格组成,每个单元格无论空间(使用1表示),无论是障碍(使用0为了表示).你的任务是找到一个动作序列最短的从开始到结束,其中UDLR同比分别增长.下一个.左.向右移动到下一 ...