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曾经。锁定的功能是由Synchronizedkeyword来实现的。
  14.  
  15. */
  16. public class Lockers {
  17.  
  18. /**
  19. * 測试Lock的使用。
  20.  
  21. 在方法中使用Lock。能够避免使用Synchronizedkeyword。
  22.  
  23. */
  24. public static class LockTest {
  25.  
  26. Lock lock = new ReentrantLock();// 锁
  27. double value = 0d; // 值
  28. int addtimes = 0;
  29.  
  30. /**
  31. * 添加value的值。该方法的操作分为2步,并且相互依赖,必须实如今一个事务中
  32. * 所以该方法必须同步。曾经的做法是在方法声明中使用Synchronizedkeyword。
  33. */
  34. public void addValue(double v) {
  35. lock.lock();// 取得锁
  36. System.out.println("LockTest to addValue: " + v + " "
  37. + System.currentTimeMillis());
  38. try {
  39. Thread.sleep(1000);
  40. } catch (InterruptedException e) {
  41. }
  42. this.value += v;
  43. this.addtimes++;
  44. lock.unlock();// 释放锁
  45. }
  46.  
  47. public double getValue() {
  48. return this.value;
  49. }
  50. }
  51. public static void testLockTest() throws Exception{
  52. final LockTest lockTest = new LockTest();
  53. // 新建任务1。调用lockTest的addValue方法
  54. Runnable task1 = new Runnable(){
  55. public void run(){
  56. lockTest.addValue(55.55);
  57. }
  58. };
  59. // 新建任务2,调用lockTest的getValue方法
  60. Runnable task2 = new Runnable(){
  61. public void run(){
  62. System.out.println("value: " + lockTest.getValue());
  63. }
  64. };
  65. // 新建任务运行服务
  66. ExecutorService cachedService = Executors.newCachedThreadPool();
  67. Future future = null;
  68. // 同一时候运行任务1三次。由于addValue方法使用了锁机制。所以。实质上会顺序运行
  69. for (int i=0; i<3; i++){
  70. future = cachedService.submit(task1);
  71. }
  72. // 等待最后一个任务1被运行完
  73. future.get();
  74. // 再运行任务2。输出结果
  75. future = cachedService.submit(task2);
  76. // 等待任务2运行完后,关闭任务运行服务
  77. future.get();
  78. cachedService.shutdownNow();
  79. }
  80.  
  81. /**
  82. * ReadWriteLock内置两个Lock。一个是读的Lock,一个是写的Lock。
  83.  
  84. * 多个线程可同一时候得到读的Lock,但仅仅有一个线程能得到写的Lock,
  85. * 并且写的Lock被锁定后,不论什么线程都不能得到Lock。
  86.  
  87. ReadWriteLock提供的方法有:
  88. * readLock(): 返回一个读的lock
  89. * writeLock(): 返回一个写的lock, 此lock是排他的。
  90.  
  91. * ReadWriteLockTest非常适合处理相似文件的读写操作。
  92.  
  93. * 读的时候能够同一时候读。但不能写;写的时候既不能同一时候写也不能读。
  94. */
  95. public static class ReadWriteLockTest{
  96. // 锁
  97. ReadWriteLock lock = new ReentrantReadWriteLock();
  98. // 值
  99. double value = 0d;
  100. int addtimes = 0;
  101.  
  102. /**
  103. * 添加value的值,不同意多个线程同一时候进入该方法
  104. */
  105. public void addValue(double v) {
  106. // 得到writeLock并锁定
  107. Lock writeLock = lock.writeLock();
  108. writeLock.lock();
  109. System.out.println("ReadWriteLockTest to addValue: " + v + " "
  110. + System.currentTimeMillis());
  111. try {
  112. Thread.sleep(1000);
  113. } catch (InterruptedException e) {
  114. }
  115. try {
  116. // 做写的工作
  117. this.value += v;
  118. this.addtimes++;
  119. } finally {
  120. // 释放writeLock锁
  121. writeLock.unlock();
  122. }
  123. }
  124. /**
  125. * 获得信息。当有线程在调用addValue方法时。getInfo得到的信息可能是不对的。
  126. * 所以,也必须保证该方法在被调用时,没有方法在调用addValue方法。
  127. */
  128. public String getInfo() {
  129. // 得到readLock并锁定
  130. Lock readLock = lock.readLock();
  131. readLock.lock();
  132. System.out.println("ReadWriteLockTest to getInfo "
  133. + System.currentTimeMillis());
  134. try {
  135. Thread.sleep(1000);
  136. } catch (InterruptedException e) {
  137. }
  138. try {
  139. // 做读的工作
  140. return this.value + " : " + this.addtimes;
  141. } finally {
  142. // 释放readLock
  143. readLock.unlock();
  144. }
  145. }
  146. }
  147.  
  148. public static void testReadWriteLockTest() throws Exception{
  149. final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();
  150. // 新建任务1,调用lockTest的addValue方法
  151. Runnable task_1 = new Runnable(){
  152. public void run(){
  153. readWriteLockTest.addValue(55.55);
  154. }
  155. };
  156. // 新建任务2,调用lockTest的getValue方法
  157. Runnable task_2 = new Runnable(){
  158. public void run(){
  159. System.out.println("info: " + readWriteLockTest.getInfo());
  160. }
  161. };
  162. // 新建任务运行服务
  163. ExecutorService cachedService_1 = Executors.newCachedThreadPool();
  164. Future future_1 = null;
  165. // 同一时候运行5个任务。当中前2个任务是task_1,后两个任务是task_2
  166. for (int i=0; i<2; i++){
  167. future_1 = cachedService_1.submit(task_1);
  168. }
  169. for (int i=0; i<2; i++){
  170. future_1 = cachedService_1.submit(task_2);
  171. }
  172. // 最后一个任务是task_1
  173. future_1 = cachedService_1.submit(task_1);
  174. // 这5个任务的运行顺序应该是:
  175. // 第一个task_1先运行,第二个task_1再运行。这是由于不能同一时候写。所以必须等。
  176. // 然后2个task_2同一时候运行;这是由于在写的时候。就不能读,所以都等待写结束,
  177. // 又由于能够同一时候读,所以它们同一时候运行
  178. // 最后一个task_1再运行。这是由于在读的时候,也不能写,所以必须等待读结束后。才干写。
  179.  
  180. // 等待最后一个task_2被运行完
  181. future_1.get();
  182. cachedService_1.shutdownNow();
  183. }
  184.  
  185. public static void main(String[] args) throws Exception{
  186. Lockers.testLockTest();
  187. System.out.println("---------------------");
  188. Lockers.testReadWriteLockTest();
  189. }
  190. }

版权声明:本文博主原创文章,博客,未经同意不得转载。

【Java先进】Lock、通过使用线程池的更多相关文章

  1. java多线程总结五:线程池的原理及实现

    1.线程池简介:     多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.        假设一个服务器完成一项任务所需时间为:T1 创 ...

  2. Java 1.ExecutorService四种线程池的例子与说明

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...

  3. Java 使用new Thread和线程池的区别

    本文转至:https://www.cnblogs.com/cnmenglang/p/6273761.html , 孟凡柱的专栏 的博客,在此谢谢博主! 1.new Thread的弊端执行一个异步任务你 ...

  4. (Java多线程系列九)线程池

    线程池 1.什么是线程池 线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程.线程池中线程的数量通常取决于可用内存数量和应用程序的需求. ...

  5. Java第二十七天,线程池

    1.什么情况下需要线程池? 频絮创建线程就会大大降低系统的效率,那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在java中可以通过线程池来达到这样的效 ...

  6. Java 四种内置线程池

    引言 我们之前使用线程的时候都是使用 new Thread 来进行线程的创建,但是这样会有一些问题 每次 new Thread 新建对象性能差 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可 ...

  7. Java并发(三)线程池原理

    Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池能够带来3个好处. 1. 降低资源消耗.通过重复利用已创建的线程降低线程 ...

  8. Java提供的几种线程池

    线程池,顾名思义,放线程的池子嘛,这个池子可以存放多少线程取决于你自己采用什么样的线程池,你的硬件资源,以及并发线程的数量.JDK提供了下面的四种线程池: 固定线程数的线程池 最简单的 在Java中创 ...

  9. 【重学Java】多线程进阶(线程池、原子性、并发工具类)

    线程池 线程状态介绍 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.线程对象在不同的时期有不同的状态.那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定 ...

  10. 转:Java Web应用中调优线程池的重要性

    不论你是否关注,Java Web应用都或多或少的使用了线程池来处理请求.线程池的实现细节可能会被忽视,但是有关于线程池的使用和调优迟早是需要了解的.本文主要介绍Java线程池的使用和如何正确的配置线程 ...

随机推荐

  1. JDK动态代理简单小程序

    Jdk动态代理 1.动态代理使用的情况:需要在多个方法上加上相同的逻辑的时候,需要用到动态代理. 原因:在多个方法上写相同的逻辑,第一费事,第二在不用的时候维护麻烦 使用动态代理需要用到两个类:分别为 ...

  2. Mysql rr和rc隔离

    REPEATABLE READ This is the default isolation level for InnoDB. For consistent reads, there is an im ...

  3. Redis slowlog

    和mongo的slowlog一样,redis中对于操作时间较长(默认为10秒)的命令也会记录下来,不过它将它们保存在redisServer结构中的slowlog这个链表中,新进来的log排在链表头部, ...

  4. 因特网的IP协议是不可靠无连接的,那为什么当初不直接把它设计为可靠的?

    因特网使用的IP协议是无连接的,因此其传输是不可靠的. 这样easy使人们感到因特网非常不可靠,那为什么当初不直接把它设计为可靠的? 先打一个例如.邮局寄送的平信非常像无连接的IP数据报.每封平信可能 ...

  5. 开源mp3播放器--madplay 编译和移植 简记

    madplay是一款开源的mp3播放器. http://madplay.sourcearchive.com/ 下面简单记录一下madplay的编译与移植到ARM开发板上的过程 一.编译x86版本的ma ...

  6. NET之全平台一体化

    NET之全平台一体化的体验 一.前言 近来利用空闲时间研究了一下Xamarin的技术,想想既然提供了如此好的支持,就该尝试一切可能,来一个”大小通吃“. 何为全平台:APP包括Android.IOS. ...

  7. FZU2179(数位dp)

    传送门:Chriswho 题意:求区间[1,n]内能整除自己本身各位数字的数的个数. 分析:这题跟CF 55D Beautiful numbers一样的,一个数能被它的所有非零数位整除,则能被它们的最 ...

  8. 基于Java的开源CMS系统选择(转)

    CMS概述 对于网站CMS系统而言,基于PHP的是主流,如Drupal/Joomla在各个主流虚拟机提供商上都是标准配置,也被广泛使用. 但如果你拥有Java团队,或者项目目标是想建立一个企业网使用的 ...

  9. XML,Object,Json分析转换Xstream采用

    XML,Object,Json转换之浅析Xstream的使用 请尊重他人的劳动成果,转载请注明出处:XML,Object,Json转换之浅析Xstream的使用 XStream的是一个简单的库.主要用 ...

  10. 在maven仓库中查找jar

    findmaven.net是一个查找Jar和查找Maven的Maven仓库搜索引擎,它能够依据Java开发人员提供的Class名或者Jar名找到包括它的Jar.同一时候提供Jar的Maven仓库链接. ...