Cyh的博客
Email:kissyan4916@163.com
posts - 26, comments - 19, trackbacks - 0, articles - 220
导航
BlogJava
首页
新随笔
联系
聚合
管理
公告
一直努力努力努力,像奴隶奴隶奴隶!~~
<
2024年11月
>
日
一
二
三
四
五
六
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
常用链接
我的随笔
我的文章
我的评论
我的参与
最新评论
随笔档案
(25)
2011年5月 (1)
2010年4月 (12)
2010年1月 (1)
2009年12月 (2)
2009年6月 (1)
2009年4月 (4)
2009年2月 (4)
文章分类
(219)
Android(26)
DB(5)
J2EE(31)
J2SE(79)
JavaScript(15)
others(47)
SOA&Web Service(1)
中间件(1)
软件工程(12)
软件架构(2)
文章档案
(220)
2011年8月 (1)
2010年12月 (23)
2010年11月 (2)
2010年8月 (5)
2010年7月 (2)
2010年6月 (2)
2010年5月 (1)
2010年4月 (12)
2010年3月 (28)
2010年2月 (5)
2010年1月 (23)
2009年12月 (39)
2009年6月 (14)
2009年5月 (31)
2009年3月 (2)
2009年2月 (29)
2009年1月 (1)
新闻档案
(66)
2010年10月 (1)
2010年9月 (5)
2010年8月 (11)
2010年7月 (21)
2010年6月 (13)
2010年5月 (8)
2010年4月 (5)
2009年11月 (2)
相册
Ryan
收藏夹
(7)
JAVA(7)
最新随笔
1. 集成FCKeditor 3.5.3
2. android自适应屏幕方向和大小
3. Android游戏开发之旅(二十) 双按事件捕获
4. Android游戏开发之旅(十八) SoundPool类
5. Android游戏开发之旅(十九) 分辨率大全
6. Android游戏开发之旅(十七) 图像渐变特效
7. Android游戏开发之旅(十六) 异步音乐播放
8. Android游戏开发之旅(十四) 游戏开发实战一
9. Android游戏开发之旅(十五) 按键中断处理
10. Android游戏开发之旅(十二)Sensor重力感应(2)
搜索
最新评论
1. re: struts2 checkboxlist标签的使用
同居同意同意
--yuk
2. re: struts2 checkboxlist标签的使用
ss
--d
3. re: JavaMail(4)--使用POP3接收邮件
邮件信息可以打印出来,可是下载邮件会出错是什么原因?
--琳喵喵0721
4. re: JavaMail(4)--使用POP3接收邮件
评论内容较长,点击标题查看
--流风
5. re: 操作PDF文件
评论内容较长,点击标题查看
--ly.wolf
阅读排行榜
1. struts2 checkboxlist标签的使用(18223)
2. struts2异常拦截器(5857)
3. struts2迭代标签(3845)
4. 用freemind 秒杀Spring Security(1914)
5. 加载顺序会影响对spring bean 的调用。(1489)
线程--锁
Posted on 2009-12-22 21:10
啥都写点
阅读(496)
评论(0)
编辑
收藏
所属分类:
J2SE
ReentrantLock类实现了Lock接口,通过它可以完全取代synchronized关键字
ReentrantLock的lock方法取得锁,如果该锁定没有被其他线程占据,则获取该锁定并返回,将保持计数器置为1;如果当前线程已经占据锁,则立即返回,将保持计数器加1;如果锁定被其他线程占据,则当前线程进入睡眠状态,等待其他线程释放锁,此事保持计数器为1.
ReentrantLock的unlock方法释放锁,如果当前线程是锁的占有者,则将保持计数器减1,如果保持计算器等于0,则释放锁。如果当前线程不是锁的占有者,则抛出异常。
ReadWriteLock是一个继承Lock的接口,定义了读写锁。它的一个实现类是ReentrantReadWriteLock。
ReentrantReadWriteLock的writeLock方法获得用于写入操作的锁定,当获得写入锁时,其他线程想进行读写操作都必须等待。
ReentrantReadWriteLock的readLock方法获得用于读操作的锁定,当获得读取锁时,其他读的线程可以继续获得读取锁,但是不能获得写入锁。
package
book.j2se5.thread;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
import
java.util.concurrent.Future;
import
java.util.concurrent.locks.Lock;
import
java.util.concurrent.locks.ReadWriteLock;
import
java.util.concurrent.locks.ReentrantLock;
import
java.util.concurrent.locks.ReentrantReadWriteLock;
/** */
/**
* Lockers
* 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性,
* 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作,
* 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。
*/
public
class
Lockers
{
/** */
/**
* 测试Lock的使用。在方法中使用Lock,可以避免使用Synchronized关键字。
*/
public
static
class
LockTest
{
Lock lock
=
new
ReentrantLock();
//
锁
double
value
=
0d;
//
值
int
addtimes
=
0
;
/** */
/**
* 增加value的值,该方法的操作分为2步,而且相互依赖,必须实现在一个事务中
* 所以该方法必须同步,以前的做法是在方法声明中使用Synchronized关键字。
*/
public
void
addValue(
double
v)
{
lock.lock();
//
取得锁
System.out.println(
"
LockTest to addValue:
"
+
v
+
"
"
+
System.currentTimeMillis());
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
}
this
.value
+=
v;
this
.addtimes
++
;
lock.unlock();
//
释放锁
}
public
double
getValue()
{
return
this
.value;
}
}
public
static
void
testLockTest()
throws
Exception
{
final
LockTest lockTest
=
new
LockTest();
//
新建任务1,调用lockTest的addValue方法
Runnable task1
=
new
Runnable()
{
public
void
run()
{
lockTest.addValue(
55.55
);
}
}
;
//
新建任务2,调用lockTest的getValue方法
Runnable task2
=
new
Runnable()
{
public
void
run()
{
System.out.println(
"
value:
"
+
lockTest.getValue());
}
}
;
//
新建任务执行服务
ExecutorService cachedService
=
Executors.newCachedThreadPool();
Future future
=
null
;
//
同时执行任务1三次,由于addValue方法使用了锁机制,所以,实质上会顺序执行
for
(
int
i
=
0
; i
<
3
; i
++
)
{
future
=
cachedService.submit(task1);
}
//
等待最后一个任务1被执行完
future.get();
//
再执行任务2,输出结果
future
=
cachedService.submit(task2);
//
等待任务2执行完后,关闭任务执行服务
future.get();
cachedService.shutdownNow();
}
/** */
/**
* ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。
* 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock,
* 而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有:
* readLock(): 返回一个读的lock
* writeLock(): 返回一个写的lock, 此lock是排他的。
* ReadWriteLockTest很适合处理类似文件的读写操作。
* 读的时候可以同时读,但不能写;写的时候既不能同时写也不能读。
*/
public
static
class
ReadWriteLockTest
{
//
锁
ReadWriteLock lock
=
new
ReentrantReadWriteLock();
//
值
double
value
=
0d;
int
addtimes
=
0
;
/** */
/**
* 增加value的值,不允许多个线程同时进入该方法
*/
public
void
addValue(
double
v)
{
//
得到writeLock并锁定
Lock writeLock
=
lock.writeLock();
writeLock.lock();
System.out.println(
"
ReadWriteLockTest to addValue:
"
+
v
+
"
"
+
System.currentTimeMillis());
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
}
try
{
//
做写的工作
this
.value
+=
v;
this
.addtimes
++
;
}
finally
{
//
释放writeLock锁
writeLock.unlock();
}
}
/** */
/**
* 获得信息。当有线程在调用addValue方法时,getInfo得到的信息可能是不正确的。
* 所以,也必须保证该方法在被调用时,没有方法在调用addValue方法。
*/
public
String getInfo()
{
//
得到readLock并锁定
Lock readLock
=
lock.readLock();
readLock.lock();
System.out.println(
"
ReadWriteLockTest to getInfo
"
+
System.currentTimeMillis());
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e)
{
}
try
{
//
做读的工作
return
this
.value
+
"
:
"
+
this
.addtimes;
}
finally
{
//
释放readLock
readLock.unlock();
}
}
}
public
static
void
testReadWriteLockTest()
throws
Exception
{
final
ReadWriteLockTest readWriteLockTest
=
new
ReadWriteLockTest();
//
新建任务1,调用lockTest的addValue方法
Runnable task_1
=
new
Runnable()
{
public
void
run()
{
readWriteLockTest.addValue(
55.55
);
}
}
;
//
新建任务2,调用lockTest的getValue方法
Runnable task_2
=
new
Runnable()
{
public
void
run()
{
System.out.println(
"
info:
"
+
readWriteLockTest.getInfo());
}
}
;
//
新建任务执行服务
ExecutorService cachedService_1
=
Executors.newCachedThreadPool();
Future future_1
=
null
;
//
同时执行5个任务,其中前2个任务是task_1,后两个任务是task_2
for
(
int
i
=
0
; i
<
2
; i
++
)
{
future_1
=
cachedService_1.submit(task_1);
}
for
(
int
i
=
0
; i
<
2
; i
++
)
{
future_1
=
cachedService_1.submit(task_2);
}
//
最后一个任务是task_1
future_1
=
cachedService_1.submit(task_1);
//
这5个任务的执行顺序应该是:
//
第一个task_1先执行,第二个task_1再执行;这是因为不能同时写,所以必须等。
//
然后2个task_2同时执行;这是因为在写的时候,就不能读,所以都等待写结束,
//
又因为可以同时读,所以它们同时执行
//
最后一个task_1再执行。这是因为在读的时候,也不能写,所以必须等待读结束后,才能写。
//
等待最后一个task_2被执行完
future_1.get();
cachedService_1.shutdownNow();
}
public
static
void
main(String[] args)
throws
Exception
{
Lockers.testLockTest();
System.out.println(
"
---------------------
"
);
Lockers.testReadWriteLockTest();
}
}
--
学海无涯
Powered by:
BlogJava
Copyright © 啥都写点