修改锁的公平性

  ReentrantLock和ReentrantReadWriteLock类的构造器都含有一个布尔参数fair,它允许你控制这两个类的行为。默认fair值为false,它称为非公平模式(Non-Fair Mode)。在非公平模式下,当有很多线程在等待锁(ReentrantLock和ReentrantReadWriteLock)时,锁将选择它们当中的一个来访问临界区,这个选择是没有任何约束的。如果fair值是true,则称为公平模式(Fair Mode)。在公平模式下,当有很多线程在等待锁(ReentrantLock和ReentrantReadWriteLock)时,锁将选择它们中的一个来访问临界区,而且选择的是等待时间最长的。这两种模式只适用于lock()和unlock()方法。而Lock接口的tryLock()方法没有将线程置于休眠,fair属性并不影响这个方法。

  下面我们将修改“使用锁实现同步”当中的范例来使用这个属性,并观察公平模式和非公平模式之间的区别。

1. 创建一个打印队列类PrintQueue。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PrintQueue {
    //声明一个锁对象,并且用ReentrantLock类初始化
    private final Lock queueLock = new ReentrantLock(true);
    //实现打印方法
    public void printJob(Object doucument){
        queueLock.lock();
        Long duration = (long) (Math.random()*10000);
        System.out.println(Thread.currentThread().getName()+": PrintQueue: Printing a Job during "+(duration/1000)+" seconds");
        try {
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
        queueLock.lock();
        duration = (long) (Math.random()*10000);
        System.out.println(Thread.currentThread().getName()+": PrintQueue: Printing a Job during "+(duration/1000)+" seconds");
        try {
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
    }
    
}

2. 创建打印工作类Job并且实现Runnable接口。

public class Job implements Runnable {
    private PrintQueue printQueue;
    public Job(PrintQueue printQueue){
        this.printQueue = printQueue;
    }
    @Override
    public void run() {
        System.out.printf("%s: Going to print a document\n", Thread.currentThread().getName());
        printQueue.printJob(new Object());
        System.out.printf("%s: The Document has been printed\n", Thread.currentThread().getName());
    }

}

3. 创建范例的主类Main

public class Main {

    public static void main(String[] args) {
        //创建一个共享的打印队列对象
        PrintQueue printQueue = new PrintQueue();
        //创建10个打印工作Job对象
        Thread threads[] = new Thread[10];
        for(int i=0;i<10;i++){
            threads[i] = new Thread(new Job(printQueue), "Thread"+i);
        }
        //启动10个线程
        try {
            for(int i=0;i<10;i++){
                threads[i].start();
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

4. 程序运行结果如下

Thread0: Going to print a document
Thread0: PrintQueue: Printing a Job during 4 seconds
Thread3: Going to print a document
Thread2: Going to print a document
Thread1: Going to print a document
Thread4: Going to print a document
Thread5: Going to print a document
Thread6: Going to print a document
Thread7: Going to print a document
Thread8: Going to print a document
Thread9: Going to print a document
Thread3: PrintQueue: Printing a Job during 9 seconds
Thread2: PrintQueue: Printing a Job during 3 seconds
Thread1: PrintQueue: Printing a Job during 7 seconds
Thread4: PrintQueue: Printing a Job during 7 seconds
Thread5: PrintQueue: Printing a Job during 5 seconds
Thread6: PrintQueue: Printing a Job during 6 seconds
Thread7: PrintQueue: Printing a Job during 0 seconds
Thread8: PrintQueue: Printing a Job during 7 seconds
Thread9: PrintQueue: Printing a Job during 5 seconds
Thread0: PrintQueue: Printing a Job during 4 seconds
Thread0: The Document has been printed
Thread3: PrintQueue: Printing a Job during 5 seconds
Thread3: The Document has been printed
Thread2: PrintQueue: Printing a Job during 1 seconds
Thread2: The Document has been printed
Thread1: PrintQueue: Printing a Job during 9 seconds
Thread1: The Document has been printed
Thread4: PrintQueue: Printing a Job during 4 seconds
Thread4: The Document has been printed
Thread5: PrintQueue: Printing a Job during 2 seconds
Thread5: The Document has been printed
Thread6: PrintQueue: Printing a Job during 5 seconds
Thread6: The Document has been printed
Thread7: PrintQueue: Printing a Job during 9 seconds
Thread7: The Document has been printed
Thread8: PrintQueue: Printing a Job during 4 seconds
Thread8: The Document has been printed
Thread9: PrintQueue: Printing a Job during 6 seconds
Thread9: The Document has been printed

 

posted @ 2015-10-24 19:28  ~风轻云淡~  阅读(266)  评论(0编辑  收藏  举报