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