2.4 公平锁
ReentrantLock和ReentrantReadWriteLock类的构造器允许名为公平的布尔参数,这个参数允许你控制这两个类的行为。false是默认值,这意味着以非公平模式运行。在这种模式下,当有些线程等待一个锁时,这个锁不得不选择它们中的一个去访问临界部分,它做出选择没有参考任何标准。true值称之为公平模式,当多个线程等待一个锁时,这个锁就会根据等待时间最长的线程作为其访问临界部分的线程。考虑到,先前解释过的行为仅仅被使用在lock()和unlock()方法中。
如果Lock接口使用的话,tryLock()方法不会让线程睡眠,公平锁属性不会影响它的功能。
下面,我创建一个实例来阐明这个原理。
定义Task类,这个类中执行有关的业务打印操作。
import java.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
public class Task {
/**
* Creates a lock to control the access to thequeue.
* With the boolean attribute, we control thefairness of
* the Lock
*/
private finalLock queueLock=new ReentrantLock(true);
/**
* Method that prints the Job. The printing isdivided in two phase two
* show how the fairness attribute affects theelection of the thread who
* has the control of the lock
* @param document The document to print
*/
public voidprintTask(Object document){
queueLock.lock();
try {
Long duration= (long) 1000;
System.out.printf("%s: Task 1: Printing a task Job during %d seconds by creation order.\n",
Thread.currentThread().getName(),(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
queueLock.lock();
try {
Long duration=(long)(Math.random()*10000);
System.out.printf("%s: Task 2: Printing a task Job during %d seconds\n",
Thread.currentThread().getName(),(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
}
}
定义Worker类,实现run()方法。
public class Worker implements Runnable{
/**
* The queue to send the documents
*/
private Task printQueue;
/**
* Constructor of the class. Initializes theprint queue
* @param printQueue the print queue to send the documents
*/
public Worker(Task printQueue){
this.printQueue=printQueue;
}
/**
* Core method of the Job. Sends the documentto the queue
*/
@Override
public voidrun() {
System.out.printf("%s: Going to print a job\n",
Thread.currentThread().getName());
printQueue.printTask(new Object());
System.out.printf("%s: The document has been printed\n",
Thread.currentThread().getName());
}
public staticvoidmain(String []args){
// Creates the print queue task
Task printQueue=new Task();
// Creates ten task and the Threads to run them
Thread thread[]=new Thread[10];
for (int i=0; i<10; i++){
thread[i]=new Thread(new Worker(printQueue),"Thread "+i);
}
// Launch a thread ever 0.1 seconds
for (int i=0; i<10; i++){
thread[i].start();
try {
Thread.sleep(100);
} catch (InterruptedExceptione) {
e.printStackTrace();
}
}
}
}
执行结果:
Thread0: Going to print a job
Thread0: Task 1: Printing a task Job during 1 seconds by creation order .
Thread1: Going to print a job
Thread2: Going to print a job
Thread3: Going to print a job
Thread4: Going to print a job
Thread5: Going to print a job
Thread6: Going to print a job
Thread7: Going to print a job
Thread8: Going to print a job
Thread9: Going to print a job
Thread1: Task 1: Printing a task Job during 1 seconds by creation order .
Thread2: Task 1: Printing a task Job during 1 seconds by creation order .
Thread3: Task 1: Printing a task Job during 1 seconds by creation order .
Thread4: Task 1: Printing a task Job during 1 seconds by creation order .
Thread5: Task 1: Printing a task Job during 1 seconds by creation order .
Thread6: Task 1: Printing a task Job during 1 seconds by creation order .
Thread7: Task 1: Printing a task Job during 1 seconds by creation order .
Thread8: Task 1: Printing a task Job during 1 seconds by creation order .
Thread9: Task 1: Printing a task Job during 1 seconds by creation order .
Thread0: Task 2: Printing a task Job during 0 seconds
Thread0: The document has been printed
Thread1: Task 2: Printing a task Job during 7 seconds
Thread1: The document has been printed
Thread2: Task 2: Printing a task Job during 1 seconds
Thread2: The document has been printed
Thread3: Task 2: Printing a task Job during 0 seconds
Thread3: The document has been printed
Thread4: Task 2: Printing a task Job during 8 seconds
Thread4: The document has been printed
Thread5: Task 2: Printing a task Job during 7 seconds
Thread5: The document has been printed
Thread6: Task 2: Printing a task Job during 1 seconds
Thread6: The document has been printed
Thread7: Task 2: Printing a task Job during 7 seconds
Thread7: The document has been printed
Thread8: Task 2: Printing a task Job during 8 seconds
Thread8: The document has been printed
Thread9: Task 2: Printing a task Job during 0 seconds
Thread 9: The document has been printed