01.import java.util.concurrent.ExecutorService;
02.import java.util.concurrent.Executors;
03.import java.util.concurrent.Future;
04.import java.util.concurrent.locks.Lock;
05.import java.util.concurrent.locks.ReadWriteLock;
06.import java.util.concurrent.locks.ReentrantLock;
07.import java.util.concurrent.locks.ReentrantReadWriteLock;
08.
09./**
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.}
分享到:
相关推荐
1. Java多线程学习(一)Java多线程入门 2. Java多线程学习(二)synchronized...7. Java多线程学习(六)Lock锁的使用 8. Java多线程学习(七)并发编程中一些问题 9. Java多线程学习(八)线程池与Executor 框架
java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...
1. stop() 和 suspend() 方法为何不推荐使用? 2. sleep() 和 wait() 有什么区别? 3. 同步和异步有何异同,...5. 简述 synchronized 和 java.util.concurrent.locks.Lock 的异同? 6. 概括的解释下线程的几种可用状态。
多线程买票是java中的一个经典案例,其主要思想无非包括2点,synchronized和锁,两者中,前者实现同步,后者为同步的线程提供锁,从而实现多个线程共享同一份资源时候,能够同步进行; 经典的方式是synchronized + 锁...
1.什么是多线程 2.Thread类解析 3.使用多线程需要注意的问题 4.synchronized锁和lock锁 5.AQS 6.ReentrantLock和ReentrantReadWriteLock 7.线程池 8.死锁 9.线程常用的工具栏 10.Atomic 11.ThreadLocal
07 使用JAVA建立稳定的多线程服务器 (3) 08 线程池的介绍及简单实现 09 Java实时多任务调度过程中的安全监控设计 (3) 10 不要重新分配被锁定对象的对象引用 11 以全局的固定顺序获取多个锁来避免死锁 12 Java...
java多线程之lock。 Lock的基本用法如下,为了防止异常退出时没有释放锁,一般都在拿到锁后立马try,try住所有临界区的代码,然后finally释放锁。
1.讲解了Java多线程的基础, 包括Thread类的核心API的使用。2.讲解了在多线程中对并发访问的控制, 主要就是synchronized的使用, 由于此关键字在使用上非常灵活, 所以书中用了很多案例来介绍此关键字的使用, 为...
计算机后端-Java-Java核心基础-第20章 多线程 13. Lock锁方式解决线程安全问题.avi
(注意,本资源附带书中源代码可供参考) 多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字与实例来介绍Java线程相关的设计模式概念,并且通过实际的Java程序范例和 UML图示来一一解说,书中...
java多线程死锁预防机制研究,java多线程死锁预防机制研究
线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题。锁正是基于这种思路实现的一种...
Java多线程与线程安全实践-基于Http协议的断点续传.rar 是一个Java毕业设计项目,旨在探讨如何在Java中实现多线程和线程安全,以及如何基于Http协议实现断点续传功能。该项目提供了一个完整的源代码包,可以作为学习...
25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................
在char01包里放置Java多线程基本知识的代码。内容如下: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 在char02包里放置了Java对变量和对象并发访问的知识的代码...
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...
Lock lock.acquire() lock.release() 4. 什么是线程 threading Thread() t.start() t.join() t.name t.getName t.setName t.daemon t.is_alive() 5. 自定义线程类 继承 Thread 重写 run 6. 线程...
主要介绍了Java多线程中Lock锁的使用总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
java多线程实现生产者和消费者 ,4种实现方式,分别为synchronizated,condition和lock,信号量,阻塞队列