《Java 7 并发编程指南》学习概要 (2)Lock

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



原文地址:https://www.cnblogs.com/leeeee/p/7276434.html