## lock 框架 ##
java.util.concurrent.lock 框架是 JDK5.0 后新增的特性,作用呢是准备用来替代 synchronized 语义和 volatile 声明,属于高帅富性能,对于初级开发来说平时开发可能用不上,因为synchronized 已能很好的应用于大部分场景。如果你的项目里的多线程模块需要用更高的性能,更高的灵活性,更好的伸缩性,那么可以把原来的synchronized块替 换成lock框架下的 ReetrantLock, ReetantReadWriteLock,Condition来搭配实现。
下面贴上这3个包的简单示例代码。
1.ReetrantLock
ReetrantLock相比于synchronized一个很明显的机制差异就是ReetrantLock 可以中断一个正在等候获得锁的线程,也可以通过投票得到锁,如果不想等下去,那么就是它了。
ReetrantLock简单示例代码如下:
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
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo1 {
/** * @param args */
public static void main(String[] args) {
final Output output = new Output();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
output.print("Hello Beauty");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
output.print("HelloWorld");
}
}
}).start();
}
}
class Output {
Lock lock = new ReentrantLock();
public void print(String name) {
lock.lock();
try {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} finally {
lock.unlock();// 请记住一定要在finally块里释放锁,ReentrantLock不会自动释放锁,不然程序抛出异常
}
}
}
ReentrantReadWriteLock
ReentrantReadWriteLock是针对于共享数据的读写优化,多线程在读操作是不会产生互斥的,而在写操作时才有互斥,在大数据量的 同时读写操作时,会效率很多。
ReentrantReadWriteLock简单示例代码如下:
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
import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ThreadDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
final Queue queue = new Queue();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
queue.getData();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
queue.putData();
}
}
}).start();
}
}
class Queue{
private Object data;//被共享
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
public void getData(){
rwl.readLock().lock();//不互斥,大家都可以访问
try{
System.out.println(Thread.currentThread().getName()+"准备读取数据");
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获得数据"+this.data);
}finally{
rwl.readLock().unlock();
}
}
public void putData(){
rwl.writeLock().lock();//写锁互斥,一个线程进来,读写的其它线程都不能访问
try{
System.out.println(Thread.currentThread().getName()+"准备存入数据");
this.data = new Random().nextInt(500);
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"存入数据"+this.data);
}finally{
rwl.writeLock().unlock();//记住此操作不可省略
}
}
}
Condition
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支持多路等待,就是我们可以定义多个Condition,每个condition控制线程的一条执行通路。 传统方式只能是一路等待。
ReetrantLock简单示例代码如下:
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo3 {
public static void main(String[] args) {
final Bus bus = new Bus();
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1; i <= 50;i++){
bus.sub1();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1; i <= 50;i++){
bus.sub2();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1; i <= 50;i++){
bus.sub3();
}
}
}).start();
}
}
class Bus{
int flag = 1;
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void sub1(){
lock.lock();
try{
while(flag!=1){
try {
//this.wait();
condition1.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i <= 10; i++){
System.out.println("老大循环"+i+"次");
}
//this.notify();
condition2.signal();
flag = 2;
}finally{
lock.unlock();
}
}
public void sub2(){
lock.lock();
try{
while(flag!=2){
try {
//this.wait();
condition2.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i <= 20;i++){
System.out.println("老二"+i+"次");
}
//this.notify();
condition3.signal();
flag = 3;
}finally{
lock.unlock();
}
}
public void sub3(){
lock.lock();
try{
while(flag!=3){
try {
//this.wait();
condition3.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i <= 30;i++){
System.out.println("老三"+i+"次");
}
//this.notify();
condition1.signal();
flag = 1;
}finally{
lock.unlock();
}
}
}