1、ReentrantLock
(1)、lock()、unlock()一对方法与synchronized 意思一样,unlock()方法 要在finally里面释放。
(2)、tryLock()方法:如果一 个线程调用这个方法不能获取Lock接口的控制权时,将会立即返回并且不会使这个线程进入睡眠。这个方法返回一个boolean值,true表示这个线程 获取了锁的控制权,false则表示没有。
(3)、还有lockInterruptibly()、tryLock(long time, TimeUnit unit) 等方法。
public class PrintQueue {
private final Lock lock = new ReentrantLock();
public void printJob(Object obj) {
while (true) {
if (lock.tryLock()) {
try {
System.out.printf("%s: Going to print a document
", Thread.
currentThread().getName());
Thread.sleep((long) (Math.random() * 2000));
System.out.println(Thread.currentThread().getName()
+ ": " + obj);
System.out.printf("%s: The document has been printed
",
Thread.currentThread().getName());
break;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
try {
Thread.sleep((long) (Math.random() * 2000));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
PrintQueue printQueue = new PrintQueue();
Thread thread[] = new Thread[10];
for (int i = 0; i < 10; i++) {
thread[i] = new Thread(new Job(printQueue), "Thread " + i);
}
for (int i = 0; i < 10; i++) {
thread[i].start();
}
}
}
class Job implements Runnable {
private PrintQueue printQueue;
public Job(PrintQueue printQueue) {
this.printQueue = printQueue;
}
@Override
public void run() {
printQueue.printJob(new Object());
}
}
输出:
Thread 0: Going to print a document
Thread 0: java.lang.Object@1d4cee08
Thread 0: The document has been printed
Thread 5: Going to print a document
Thread 5: java.lang.Object@259f5e3f
Thread 5: The document has been printed
Thread 3: Going to print a document
Thread 3: java.lang.Object@1e48d65
Thread 3: The document has been printed
Thread 8: Going to print a document
Thread 8: java.lang.Object@12dfbabd
Thread 8: The document has been printed
Thread 2: Going to print a document
Thread 2: java.lang.Object@1e5cd7f9
Thread 2: The document has been printed
Thread 9: Going to print a document
Thread 9: java.lang.Object@61672c01
Thread 9: The document has been printed
Thread 1: Going to print a document
Thread 1: java.lang.Object@3c7a279c
Thread 1: The document has been printed
Thread 4: Going to print a document
Thread 4: java.lang.Object@77be91c8
Thread 4: The document has been printed
Thread 6: Going to print a document
Thread 6: java.lang.Object@551ee3
Thread 6: The document has been printed
Thread 7: Going to print a document
Thread 7: java.lang.Object@545ec940
Thread 7: The document has been printed
BUILD SUCCESSFUL (total time: 16 seconds)
2、ReadWriteLock
ReentrantReadWriteLock 提供两把锁,一把用于读操作和一把用于写操作。同时可以有多个线程执行读操作,但只有一个线程可以执行写操作。当一个线程正在执行一个写操作,不可能有任何线程执行读操作。
public class MyReadWriteLockTest {
private double value1;
private double value2;
private ReadWriteLock lock;
public MyReadWriteLockTest() {
value1 = 1.0;
value2 = 2.0;
lock = new ReentrantReadWriteLock();
}
public double getValue1() {
lock.readLock().lock();
try {
double value = value1;
return value;
} finally {
lock.readLock().unlock();
}
}
public double getValue2() {
lock.readLock().lock();
try {
double value = value2;
return value;
} finally {
lock.readLock().unlock();
}
}
public void setValues(double value1, double value2) {
lock.writeLock().lock();
try {
this.value1 = value1;
this.value2 = value2;
} finally {
lock.writeLock().unlock();
}
}
}
3、修改Lock的公平性
ReentrantLock类和 ReentrantReadWriteLock ,默认参数fair为false,即是不公平的:当有多个线程正在等待一把锁,这个锁必须选择它们中间的一个来获得进入临界区,选择任意一个是没有任何标准的。
设置fair为true值将开启公平模式:当有多个线程正在等待一把锁,这个锁必须选择它们中间的一个来获得进入临界区,它将选择等待时间最长的线程。
private Lock queueLock=new ReentrantLock(true);
private ReadWriteLock queueLock=new ReentrantReadWriteLock(true);
4、Lock中使用多个Condition
await()、signal()、signalAll() 分别对应 wait()、notify()、notifyAll().
class MyCollection {
private String[] array;
private int maxSize;
private int count;
private ReentrantLock lock;
private Condition condition1;
private Condition condition2;
public MyCollection(int maxSize) {
this.maxSize = maxSize;
array = new String[maxSize];
count = 0;
lock = new ReentrantLock();
condition1 = lock.newCondition();
condition2 = lock.newCondition();
}
public String get() {
String line = null;
lock.lock();
try {
while (count == 0) {
condition1.await();
}
line = array[count - 1];
array[count - 1] = null;
count--;
condition2.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return line;
}
public void insert(String line) {
lock.lock();
try {
while (count == maxSize) {
condition2.await();
}
array[count++] = line;
condition1.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
class Producer implements Runnable {
private MyCollection myCollection;
public Producer(MyCollection myCollection) {
this.myCollection = myCollection;
}
@Override
public void run() {
while (true) {
String line = "String_" + System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + ":" + line);
myCollection.insert(line);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
private MyCollection myCollection;
public Consumer(MyCollection myCollection) {
this.myCollection = myCollection;
}
@Override
public void run() {
while (true) {
String line = myCollection.get();
System.out.println(Thread.currentThread().getName() + ":" + line);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}