博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lock应用之 尝试锁获取
阅读量:5931 次
发布时间:2019-06-19

本文共 3022 字,大约阅读时间需要 10 分钟。

当线程请求内部锁时,如果锁已经被占用,则请求线程必须无条件等待,这往往会造成很多奇怪问题,相互等待是造成死锁的重要原因之一,著名的哲学家就餐问题就是个典型的案例。新的Lock锁提供了尝试获取锁失败自动放弃的方法tryLock(),具有更完善的错误恢复机制。

1
2
boolean 
tryLock();
boolean 
tryLock(
long 
time, TimeUnit unit) 
throws 
InterruptedException;

Lock接口定义了两个重载tryLock()函数,第一个函数表示如果锁可用则立即获得锁并返回true,如果请求的锁当前不可用则立即放弃并返回false;第二个函数表示如果请求的锁当前可用则立即获得锁并返回true,如果锁不可用则等待指定的时间,在等待期间,线程可能被中断,可能获得锁,如果等待时间结束还未获取到锁则自动放弃并返回false,明显相对第一个函数提供了更多的灵活性。

当然我们还可以自己利用循环轮询调用tryLock(),以实现轮询锁等,实现更多的灵活机制,这就是Lock相对内部锁的好处,特别是当线程需要同时获取多把不同锁时,tryLock()大有用处。

举一个实际简单应用场景,假设我们有个定时任务,定时清理垃圾,但每次清理垃圾耗费的时间可能不同,如果新任务发现上个任务还没执行完就自己结束,因为不需要这次任务。其实ScheduledExecutorService.scheduleAtFixedRate()函数就提供这样的功能,每个定时任务都是等上个任务完成才开始执行。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import 
java.util.concurrent.Executors;
import 
java.util.concurrent.ScheduledExecutorService;
import 
java.util.concurrent.TimeUnit;
import 
java.util.concurrent.locks.Lock;
import 
java.util.concurrent.locks.ReentrantLock;
public 
class 
TestTryLock {
    
private 
Lock mLock;
    
private 
volatile 
boolean 
isTimeoutEnabled;
                                                      
    
public 
TestTryLock(){
        
this
.mLock = 
new 
ReentrantLock();
        
this
.isTimeoutEnabled = 
false
;
    
}
                                                      
    
public 
void 
clearRubbish() 
throws 
InterruptedException{
        
if
(mLock.tryLock()){
            
try
{
                
System.out.println(Thread.currentThread().getName() + 
":get the lock successfully."
);
                
int 
estTime = (
int
) (
10 
* Math.random());
                
System.out.println(Thread.currentThread().getName() + 
":estimate time for finish job:" 
+ estTime);
                
TimeUnit.SECONDS.sleep(estTime);
            
}
            
finally
{
                
mLock.unlock();
            
}          
        
}
        
else
{
            
System.out.println(Thread.currentThread().getName() + 
":failed to get the lock."
);
        
}      
    
}
                                                      
    
public 
void 
clearRubbishWithTimeout() 
throws 
InterruptedException{
        
if
(mLock.tryLock(
2
, TimeUnit.SECONDS)){
            
try
{
                
System.out.println(Thread.currentThread().getName() + 
":get the lock successfully by waiting 2 seconds."
);
                
int 
estTime = (
int
) (
10 
* Math.random());
                
System.out.println(Thread.currentThread().getName() + 
":estimate time for finish job:" 
+ estTime);
                
TimeUnit.SECONDS.sleep(estTime);
            
}
            
finally
{
                
mLock.unlock();
            
}          
        
}
        
else
{
            
System.out.println(Thread.currentThread().getName() + 
":failed to get the lock after waiting 2 seconds."
);
        
}      
    
}
                                                      
    
private 
class 
Worker 
implements 
Runnable{
        
@Override
        
public 
void 
run() {
            
try 
{
                
if
(isTimeoutEnabled){
                    
clearRubbishWithTimeout();
                
}
                
else
{
                    
clearRubbish();
                
}  
                                                                  
                
isTimeoutEnabled = !isTimeoutEnabled;
            
catch 
(InterruptedException e) {
                
e.printStackTrace();
            
}
        
}      
    
}
                                                      
    
private 
class 
TimerWorker 
implements 
Runnable{
        
@Override
        
public 
void 
run() {
            
new 
Thread(
new 
Worker()).start();
        
}      
    
}
    
public 
static 
void 
main(String[] args) {
        
TestTryLock testTryLock = 
new 
TestTryLock();
        
ScheduledExecutorService service = Executors.newScheduledThreadPool(
1
);
        
service.scheduleAtFixedRate(testTryLock. 
new 
TimerWorker(), 
0
3
, TimeUnit.SECONDS);       
    
}
}

     本文转自sarchitect 51CTO博客,原文链接:http://blog.51cto.com/stevex/1301077,如需转载请自行联系原作者

你可能感兴趣的文章
曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?
查看>>
[改善Java代码]不推荐使用binarySearch对列表进行检索
查看>>
用bat 删除当前文件夹下的某类文件
查看>>
SqlServer2012自增主键跳跃增长的问题解决方案
查看>>
你真的了解UIEvent、UITouch吗?
查看>>
webpack vue2.0项目脚手架生成的webpack文件
查看>>
2014面试总结--java、数据 方向
查看>>
Linux 网卡驱动学习(一)(分析一个虚拟硬件的网络驱动样例)
查看>>
Linux下的SVN服务器搭建
查看>>
我在农业2.0的互联网创业思考 (1)
查看>>
如何在Linux中查看所有正在运行的进程
查看>>
Docker: 限制容器可用的内存
查看>>
Git 的4个阶段的撤销更改
查看>>
Downloading jQuery 3.2.1
查看>>
selenium+python自动化87-Chrome浏览器静默模式启动(headless)
查看>>
在IIS7、IIS7.5中应用程序池最优配置方案
查看>>
mybatis 整合spring之mapperLocations配置的问题
查看>>
Python time 的应用
查看>>
hadoop21---使用代理修改List,代理流程
查看>>
mysql for update语句
查看>>