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(); } } } }