线程Lock的使用

ReetrantLock类

ReetrantLock相比synchronized具有更加的灵活性。

public class MyService {
    private Lock lock = new ReentrantLock();
    public void  testMethod() {
        lock.lock();
        for (int i = 0; i < 5; i++) {
            System.out.println("ThreadName = " + Thread.currentThread().getName() + "  " + (i + 1));
        }
        lock.unlock();
    }
}


public class MyThread extends Thread {

    /** Field service */
    private MyService service;

    /**
     * Constructs MyThread
     *
     *
     * @param service
     */
    public MyThread(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod();
    }
}



public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        MyService service = new MyService();
        MyThread  a1      = new MyThread(service);
        MyThread  a2      = new MyThread(service);
        MyThread  a3      = new MyThread(service);
        MyThread  a4      = new MyThread(service);
        MyThread  a5      = new MyThread(service);
        MyThread  a6      = new MyThread(service);

        a1.start();
        a2.start();
        a3.start();
        a4.start();
        a5.start();
        a6.start();
    }
}



/*
ThreadName = Thread-1  1
ThreadName = Thread-1  2
ThreadName = Thread-1  3
ThreadName = Thread-1  4
ThreadName = Thread-1  5
ThreadName = Thread-0  1
ThreadName = Thread-0  2
ThreadName = Thread-0  3
ThreadName = Thread-0  4
ThreadName = Thread-0  5
ThreadName = Thread-2  1
ThreadName = Thread-2  2
ThreadName = Thread-2  3
ThreadName = Thread-2  4
ThreadName = Thread-2  5
ThreadName = Thread-3  1
ThreadName = Thread-3  2
ThreadName = Thread-3  3
ThreadName = Thread-3  4
ThreadName = Thread-3  5
ThreadName = Thread-4  1
ThreadName = Thread-4  2
ThreadName = Thread-4  3
ThreadName = Thread-4  4
ThreadName = Thread-4  5
ThreadName = Thread-5  1
ThreadName = Thread-5  2
ThreadName = Thread-5  3
ThreadName = Thread-5  4
ThreadName = Thread-5  5

*/

类ReetratantLock可以实现synchronized与wait()/notify()方法相结合的等待/通知模式。

类ReetratantLock需要借助Condition对象,实现多路通知。

Condition中的await()方法相当于Object()中的wait()方法。

Condition中的signal()方法相当于Object()中的notify()方法

public class MyService {

    /** Field lock */
    private Lock lock = new ReentrantLock();

    /** Field condition */
    public Condition condition = lock.newCondition();

    /**
     * Method await
     *
     */
    public void await() {
        try {
            lock.lock();
            System.out.println(" await时间为 = " + System.currentTimeMillis());
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }


    public void signal() {
        try {
            lock.lock();
            System.out.println("signal 的时间为 = " + System.currentTimeMillis());
            condition.signal();
        } finally {
            lock.unlock();
        }
    }


public class ThreadA extends Thread {

    /** Field service */
    private MyService service;

    /**
     * Constructs ThreadA
     *
     *
     * @param service
     */
    public ThreadA(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.await();
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        ThreadA   a       = new ThreadA(service);

        a.setName("A");
        a.start();
        Thread.sleep(3000);
        service.signal();
    }
}

 
/*result:
await时间为 = 1524378761637
signal 的时间为 = 1524378764638
*/

若想单独唤醒部分线程,则必须使用多个Condition对象,也就是Condition对象可以唤醒部分指定线程。有助于提高程序运行的效率。

可以先对线程分组,再唤醒指定组中线程。

public class MyService {

    /** Field lock */
    private Lock lock = new ReentrantLock();

    /** Field conditionA */
    public Condition conditionA = lock.newCondition();

    /** Field conditionB */
    public Condition conditionB = lock.newCondition();

    /**
     * Method awaitA
     *
     */
    public void awaitA() {
        try {
            lock.lock();
            System.out.println("begin awaitA 时间为; " + System.currentTimeMillis() + "  ThreadName = "
                               + Thread.currentThread().getName());
            conditionA.await();
            System.out.println("    end awaitA 时间为; " + System.currentTimeMillis() + "  ThreadName = "
                               + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method awaitB
     *
     */
    public void awaitB() {
        try {
            lock.lock();
            System.out.println("begin awaitB 时间为; " + System.currentTimeMillis() + "  ThreadName = "
                               + Thread.currentThread().getName());
            conditionB.await();
            System.out.println("    end awaitB 时间为; " + System.currentTimeMillis() + "  ThreadName = "
                               + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method signalAll_A
     *
     */
    public void signalAll_A() {
        try {
            lock.lock();
            System.out.println("  begin siginAll时间为:" + System.currentTimeMillis() + " ThreadName = "
                               + Thread.currentThread().getName());
            conditionA.signalAll();
            System.out.println("     end siginalAll时间为:" + System.currentTimeMillis() + " ThreadName = "
                               + Thread.currentThread().getName());
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method signalAll_B
     *
     */
    public void signalAll_B() {
        try {
            lock.lock();
            System.out.println("  begin siginAll时间为:" + System.currentTimeMillis() + " ThreadName = "
                               + Thread.currentThread().getName());
            conditionB.signalAll();
            System.out.println("     end siginalAll时间为:" + System.currentTimeMillis() + " ThreadName = "
                               + Thread.currentThread().getName());
        } finally {
            lock.unlock();
        }
    }
}


public class ThreadA extends Thread {

    /** Field service */
    private MyService service;

    /**
     * Constructs ThreadA
     *
     *
     * @param service
     */
    public ThreadA(MyService service) {
        super();
        this.service = service;
    }

    /**
     * Method run
     *
     */
    public void run() {
        service.awaitA();
    }
}


public class ThreadB extends Thread {

    /** Field service */
    private MyService service;

    /**
     * Constructs ThreadB
     *
     *
     * @param service
     */
    public ThreadB(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.awaitB();
    }
}



public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        ThreadA   a       = new ThreadA(service);

        a.setName("A");
        a.start();

        ThreadB b = new ThreadB(service);

        b.setName("B");
        b.start();
        Thread.sleep(3000);
        service.signalAll_A();
    }
}


/*result:
begin awaitB 时间为; 1524381997080  ThreadName = B
begin awaitA 时间为; 1524381997082  ThreadName = A
  begin siginAll时间为:1524382000081 ThreadName = main
     end siginalAll时间为:1524382000081 ThreadName = main
    end awaitA 时间为; 1524382000081  ThreadName = A
*/

由此实验可知使用ReentrantLock对象可以唤醒指定种类的线程,这是控制部分新城行为的方便方式。

实现生产者/消费者模式,一对一交替打印

public class MyService {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /** Field condition */
    private Condition condition = lock.newCondition();

    /** Field hasValue */
    private Boolean hasValue = false;

    /**
     * Method get
     *
     */
    public void get() {
        try {
            lock.lock();

            while (!hasValue) {
                condition.await();
            }

            System.out.println("打印☆");
            hasValue = false;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method set
     *
     */
    public void set() {
        try {
            lock.lock();

            while (hasValue) {
                condition.await();
            }

            System.out.println("打印★");
            hasValue = true;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


public class MyThreadA extends Thread {

    /** Field service */
    private MyService service;

    /**
     * Constructs MyThreadA
     *
     *
     * @param service
     */
    public MyThreadA(MyService service) {
        this.service = service;
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            service.set();
        }
    }
}


public class MyThreadB extends Thread {

    /** Field service */
    private MyService service;

    /**
     * Constructs MyThreadB
     *
     *
     * @param service
     */
    public MyThreadB(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            service.get();
        }
    }
}



public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        MyService service = new MyService();
        MyThreadA a       = new MyThreadA(service);

        a.start();

        MyThreadB b = new MyThreadB(service);

        b.start();
    }
}


/*result:
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
... ...
*/

公平锁和非公平锁

锁Lock分为"公平锁"和"非公平锁"。
公平锁表示西安获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。

非公平锁就是一种获取锁的抢占机制,是随机获得的锁,可能造成某些线程长期拿不到锁,结果就是不公平的。

public class Service {

    /** Field lock */
    private ReentrantLock lock;

    /**
     * Constructs Service
     *
     *
     * @param isFair
     */
    public Service(boolean isFair) {
        super();
        lock = new ReentrantLock(isFair);
    }

    /**
     * Method serviceMethod
     *
     */
    public void serviceMethod() {
        try {
            lock.lock();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + "获得锁定");
        } finally {
            lock.unlock();
        }
    }
}



public class RunFair {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final Service service  = new Service(true);
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("★线程 " + Thread.currentThread().getName() + " 运行了");
                service.serviceMethod();
            }
        };
        Thread[] threadArray = new Thread[10];

        for (int i = 0; i < 10; i++) {
            threadArray[i] = new Thread(runnable);
        }

        for (int i = 0; i < 10; i++) {
            threadArray[i].start();
        }
    }
}


/*result:
★线程 Thread-0 运行了
★线程 Thread-5 运行了
★线程 Thread-1 运行了
★线程 Thread-6 运行了
ThreadName = Thread-0获得锁定
★线程 Thread-9 运行了
★线程 Thread-8 运行了
★线程 Thread-3 运行了
★线程 Thread-2 运行了
★线程 Thread-4 运行了
★线程 Thread-7 运行了
ThreadName = Thread-5获得锁定
ThreadName = Thread-1获得锁定
ThreadName = Thread-6获得锁定
ThreadName = Thread-9获得锁定
ThreadName = Thread-8获得锁定
ThreadName = Thread-3获得锁定
ThreadName = Thread-2获得锁定
ThreadName = Thread-4获得锁定
ThreadName = Thread-7获得锁定
*/


public class RunNotFair {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final Service service  = new Service(false);
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("★线程 " + Thread.currentThread().getName() + " 运行了");
                service.serviceMethod();
            }
        };
        Thread[] threadArray = new Thread[10];

        for (int i = 0; i < 10; i++) {
            threadArray[i] = new Thread(runnable);
        }

        for (int i = 0; i < 10; i++) {
            threadArray[i].start();
        }
    }
}



/*result:
★线程 Thread-1 运行了
★线程 Thread-4 运行了
★线程 Thread-5 运行了
★线程 Thread-8 运行了
★线程 Thread-0 运行了
ThreadName = Thread-1获得锁定
★线程 Thread-9 运行了
ThreadName = Thread-4获得锁定
ThreadName = Thread-5获得锁定
ThreadName = Thread-8获得锁定
ThreadName = Thread-0获得锁定
ThreadName = Thread-9获得锁定
★线程 Thread-2 运行了
ThreadName = Thread-2获得锁定
★线程 Thread-3 运行了
ThreadName = Thread-3获得锁定
★线程 Thread-6 运行了
ThreadName = Thread-6获得锁定
★线程 Thread-7 运行了
ThreadName = Thread-7获得锁定
*/

getHoldCount()方法

int getHoldCount()方法是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。

public class Service {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /**
     * Method serviceMethod1
     *
     */
    public void serviceMethod1() {
        try {
            lock.lock();
            System.out.println("serviceMethod1 getHoldCount = " + lock.getHoldCount());
            serviceMethod2();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method serviceMethod2
     *
     */
    public void serviceMethod2() {
        try {
            lock.lock();
            System.out.println("serviceMethod2 getHoldCount = " + lock.getHoldCount());
        } finally {
            lock.unlock();
        }
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        Service service = new Service();

        service.serviceMethod1();
    }
}


/*
serviceMethod1 getHoldCount = 1
serviceMethod2 getHoldCount = 2

*/

getQueueLength()方法

int getQueueLength()方法的作用是返回正等待获取此锁定的线程估计数。

public class Service {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    public ReentrantLock getLock() {
        return lock;
    }

    public void setLock(ReentrantLock lock) {
        this.lock = lock;
    }

    /**
     * Method serviceMethod1
     *
     */
    public void serviceMethod1() {
        try {
            lock.lock();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + "进入方法");
            Thread.sleep(Integer.MAX_VALUE);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        final Service service  = new Service();
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service.serviceMethod1();
            }
        };
        Thread[] threadArray = new Thread[10];

        for (int i = 0; i < 10; i++) {
            threadArray[i] = new Thread(runnable);
        }

        for (int i = 0; i < 10; i++) {
            threadArray[i].start();
        }

        Thread.sleep(2000);
        System.out.println("有线程数:" + service.getLock().getQueueLength() + "  在等待线程!");
    }
}


/*result:
ThreadName = Thread-0进入方法
有线程数:9  在等待线程!
*/

getWaitQueueLength()方法

int getWaitQueueLength(Condition condition)方法,作用是返回等待与此锁定相关的给定条件Condition的线程估计数。

public class Service {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /** Field condition */
    private Condition condition = lock.newCondition();

    /**
     * Method notifyMethod
     *
     */
    public void notifyMethod() {
        try {
            lock.lock();
            System.out.println("有 " + lock.getWaitQueueLength(condition) + "个线程正在等待");
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method waitMethod
     *
     */
    public void waitMethod() {
        try {
            lock.lock();
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        final Service service  = new Service();
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];

        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(runnable);
        }

        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }

        Thread.sleep(2000);
        service.notifyMethod();
    }
}


/*result:
有 10个线程正在等待 

*/


hasQueuedThread()方法

方法boolean hasQueuedThread(Thread thread)的作用是查询是指定的线程是否正在等待。

hasQueuedThreads()方法

方法boolean hasQueuedThreads()的作用是查询是否有线程正在等待获取此锁定。

public class Service {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /** Field condition */
    private Condition condition = lock.newCondition();

    /**
     * Method waitMethod
     *
     */
    public void waitMethod() {
        try {
            lock.lock();
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method getCondition
     *
     *
     * @return
     */
    public Condition getCondition() {
        return condition;
    }

    /**
     * Method setCondition
     *
     *
     * @param condition
     */
    public void setCondition(Condition condition) {
        this.condition = condition;
    }

    /**
     * Method getLock
     *
     *
     * @return
     */
    public ReentrantLock getLock() {
        return lock;
    }

    /**
     * Method setLock
     *
     *
     * @param lock
     */
    public void setLock(ReentrantLock lock) {
        this.lock = lock;
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        final Service service  = new Service();
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread threadA = new Thread(runnable);

        threadA.start();
        Thread.sleep(500);

        Thread threadB = new Thread(runnable);

        threadB.start();
        Thread.sleep(500);
        System.out.println(service.getLock().hasQueuedThread(threadA));
        System.out.println(service.getLock().hasQueuedThread(threadB));
        System.out.println(service.getLock().hasQueuedThreads());
    }
}

/*result:
false
true
true
*/

hasWaiters()方法

方法boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的Codition

public class Service {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /** Field condition */
    private Condition condition = lock.newCondition();

    /**
     * Method notifyMethod
     *
     */
    public void notifyMethod() {
        try {
            lock.lock();
            System.out.println(" 有没有线程正在等待condition? " + lock.hasWaiters(condition) + " 线程数是多少? "
                               + lock.getWaitQueueLength(condition));
            condition.signal();
        } finally {
            lock.unlock();
        }
    }

    /**
     * Method waitMethod
     *
     */
    public void waitMethod() {
        try {
            lock.lock();
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        final Service service  = new Service();
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread[] threads = new Thread[10];

        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(runnable);
        }

        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }

        Thread.sleep(2000);
        service.notifyMethod();
    }
}

/*result:
 有没有线程正在等待condition? true 线程数是多少? 10
*/

方法isFair(), isHeldByCurrentThread()和isLocked()

  1. 方法boolean isFair()的作用是判断是不是公平锁.默认情况ReentrantLock是非公平锁。
public class Service {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /**
     * Constructs Service
     *
     *
     * @param isFair
     */
    public Service(Boolean isFair) {
        super();
        lock = new ReentrantLock(isFair);
    }

    /**
     * Method serviceMethod
     *
     */
    public void serviceMethod() {
        try {
            lock.lock();
            System.out.println("公平锁情况:" + lock.isFair());
        } finally {
            lock.unlock();
        }
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final Service service1 = new Service(true);
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service1.serviceMethod();
            }
        };
        Thread thread = new Thread(runnable);

        thread.start();

        final Service service2 = new Service(false);

        runnable = new Runnable() {
            @Override
            public void run() {
                service2.serviceMethod();
            }
        };
        thread = new Thread(runnable);
        thread.start();
    }
}


/*result:
公平锁情况:true
公平锁情况:false
*/

Boolean isHeldByCurrentThread()方法作用是判断当前线程是否锁定。

public class Service {

    /** Field lock */
    private ReentrantLock lock;

    /**
     * Constructs Service
     *
     *
     * @param isFair
     */
    public Service(Boolean isFair) {
        super();
        lock = new ReentrantLock(isFair);
    }

    /**
     * Method serviceMethod
     *
     */
    public void serviceMethod() {
        try {
            System.out.println(lock.isHeldByCurrentThread());
            lock.lock();
            System.out.println(lock.isHeldByCurrentThread());
        } finally {
            lock.unlock();
        }
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final Service service1 = new Service(true);
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service1.serviceMethod();
            }
        };
        Thread thread = new Thread(runnable);

        thread.start();
    }
}


/*
false
true

*/

boolean isLocked()方法作用是判断是是否有线程获得该锁定。

public class Service {

    /** Field lock */
    private ReentrantLock lock;

    /**
     * Constructs Service
     *
     *
     * @param isFair
     */
    public Service(Boolean isFair) {
        super();
        lock = new ReentrantLock(isFair);
    }

    /**
     * Method serviceMethod
     *
     */
    public void serviceMethod() {
        try {
            System.out.println(lock.isLocked());
            lock.lock();
            System.out.println(lock.isLocked());
        } finally {
            lock.unlock();
        }
    }
}


public class Run {
    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final Service service1 = new Service(true);
        Runnable      runnable = new Runnable() {
            @Override
            public void run() {
                service1.serviceMethod();
            }
        };
        Thread thread = new Thread(runnable);

        thread.start();
    }
}

/*result:
false
true
*/

方法lockInterruptibly()

方法 void lockInterruptibly()的作用是:如果当前线程未被中断,则获取锁定,如果已经被中断,则出现异常。

public class MyService {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /** Field condition */
    private Condition condition = lock.newCondition();

    /**
     * Method waitMethod
     *
     */
    public void waitMethod() {
        try {

            // lock.lock();
            lock.lockInterruptibly();
            System.out.println("lock begin " + Thread.currentThread().getName());

            for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
                String newString = new String();

                Math.random();
            }

            System.out.println("lock   end " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            System.out.println("抛异常方法是:" + Thread.currentThread().getName());
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

public class Run {

    /**
     * Method main
     *
     *
     * @param args
     *
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        final MyService service     = new MyService();
        Runnable        runnableRef = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread threadA = new Thread(runnableRef);

        threadA.setName("A");
        threadA.start();
        Thread.sleep(500);

        Thread threadB = new Thread(runnableRef);

        threadB.setName("B");
        threadB.start();
        threadB.interrupt();    // 打标记
    }
}


/*
lock begin A
抛异常方法是:B
java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at com.tz4.lockInterruptiblyTest.MyService.waitMethod(MyService.java:24)
    at com.tz4.lockInterruptiblyTest.Run$1.run(Run.java:21)
    at java.lang.Thread.run(Thread.java:745)
lock   end A

*/

方法tryLock()

boolean tryLock()方法的作用是,仅在调用时锁定未被另一个线程保持的状况下,才获取锁定。

public class MyService {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /**
     * Method waitMethod
     *
     */
    public void waitMethod() {
        if (lock.tryLock()) {
            System.out.println(Thread.currentThread().getName() + " 加锁");
        } else {
            System.out.println(Thread.currentThread().getName() + " 未加锁");
        }
    }
}

public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final MyService service     = new MyService();
        Runnable        runnableRef = new Runnable() {
            @Override
            public void run() {
                service.waitMethod();
            }
        };
        Thread threadA = new Thread(runnableRef);

        threadA.setName("A ");
        threadA.start();

        Thread threadB = new Thread(runnableRef);

        threadB.setName("B ");
        threadB.start();
    }
}

/*result:
A  加锁
B  未加锁
*/

方法tryLock(long timeout, TimeUnit unit)

boolean tryLock(long timeout, TimeUnit unit)方法的作用是,如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获得锁定。

public class MyService {

    /** Field lock */
    private ReentrantLock lock = new ReentrantLock();

    /**
     * Method waitMethod
     *
     */
    public void waitMethod() {
        try {
            if (lock.tryLock(3, TimeUnit.SECONDS)) {
                System.out.println("     " + Thread.currentThread().getName() + "获得锁的时间: "
                                   + System.currentTimeMillis());
                //Thread.sleep(10000);
                Thread.sleep(100);
            } else {
                System.out.println("     " + Thread.currentThread().getName() + "未获得锁");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}


public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        final MyService service     = new MyService();
        Runnable        runnableRef = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "调用waitMethod时间: " + System.currentTimeMillis());
                service.waitMethod();
            }
        };
        Thread threadA = new Thread(runnableRef);

        threadA.setName("A ");
        threadA.start();

        Thread threadB = new Thread(runnableRef);

        threadB.setName("B ");
        threadB.start();
    }
}


/*result:
B 调用waitMethod时间: 1525003358344
A 调用waitMethod时间: 1525003358344
     A 获得锁的时间: 1525003358345
     B 未获得锁
*/

/*result:
A 调用waitMethod时间: 1525003544000
B 调用waitMethod时间: 1525003544000
     B 获得锁的时间: 1525003544001
     A 获得锁的时间: 1525003544101
*/

使用Condition实现顺序执行

使用Condition对象对线程执行的业务进行顺序规划。

public class F {

    /** Field nextPrintWho */
    public static volatile int nextPrintWho = 1;
}

public class Run {

    /** Field nextPrintWho */
    private static volatile int nextPrintWho = 1;

    /** Field lock */
    private static ReentrantLock lock = new ReentrantLock();

    /** Field conditionA */
    private static final Condition conditionA = lock.newCondition();

    /** Field conditionB */
    private static final Condition conditionB = lock.newCondition();

    /** Field conditionC */
    private static final Condition conditionC = lock.newCondition();

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        Thread threadA = new Thread() {
            public void run() {
                try {
                    lock.lock();

                    while (nextPrintWho != 1) {
                        conditionA.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadA " + (i + 1));
                    }

                    nextPrintWho = 2;
                    conditionB.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread threadB = new Thread() {
            public void run() {
                try {
                    lock.lock();

                    while (nextPrintWho != 2) {
                        conditionB.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThtradB " + (i + 1));
                    }

                    nextPrintWho = 3;
                    conditionC.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread threadC = new Thread() {
            public void run() {
                try {
                    lock.lock();

                    while (nextPrintWho != 3) {
                        conditionC.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadC " + (i + 1));
                    }

                    nextPrintWho = 1;
                    conditionA.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread[] aArray = new Thread[5];
        Thread[] bArray = new Thread[5];
        Thread[] cArray = new Thread[5];

        for (int i = 0; i < 5; i++) {
            aArray[i] = new Thread(threadA);
            bArray[i] = new Thread(threadB);
            cArray[i] = new Thread(threadC);
            aArray[i].start();
            bArray[i].start();
            cArray[i].start();
        }
    }
}
 
 
/*result:
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
*/

ReentrantReadWriteLock类

ReentrantLock()锁具有完全互斥的性质,同一时间只有一个线程可以获得锁。
而ReentrantReadWriteLock锁表示俩锁,一个是读锁也叫共享锁,另一个是写锁,也叫排它锁。可以提高线程读写效率。

public class Service {

    /** Field lock */
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    /**
     * Method read
     *
     */
    public void read() {
        try {
            try {
                lock.readLock().lock();
                System.out.println("获得读锁!" + Thread.currentThread().getName() + "  " + System.currentTimeMillis());
                Thread.sleep(10000);
            } finally {
                lock.readLock().unlock();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public class ThreadA extends Thread {

    /** Field service */
    private Service service;

    /**
     * Constructs ThreadA
     *
     *
     * @param service
     */
    public ThreadA(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.read();
    }
}

public class ThreadB extends Thread {

    /** Field service */
    private Service service;

    /**
     * Constructs ThreadB
     *
     *
     * @param service
     */
    public ThreadB(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.read();
    }
}

public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a       = new ThreadA(service);

        a.setName("A");

        ThreadB b = new ThreadB(service);

        b.setName("B");
        a.start();
        b.start();
    }
}


/*result:
获得读锁!A  1525253407220
获得读锁!B  1525253407220
*/

A,B线程几乎同时获得读锁,同时运行,应用了共享锁。也就是读读共享

public class Service {

    /** Field lock */
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * Method write
     *
     */
    public void write() {
        try {
            try {
                lock.writeLock().lock();
                System.out.println("数据写入" + Thread.currentThread().getName() + "  " + System.currentTimeMillis());
                Thread.sleep(10000);
            } finally {
                lock.writeLock().unlock();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public class ThreadA extends Thread {

    /** Field service */
    private Service service;

    /**
     * Constructs ThreadA
     *
     *
     * @param service
     */
    public ThreadA(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.write();
    }
}


public class ThreadB extends Thread {

    /** Field service */
    private Service service;

    /**
     * Constructs ThreadB
     *
     *
     * @param service
     */
    public ThreadB(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.write();
    }
}

public class Run {

    /**
     * Method main
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a       = new ThreadA(service);

        a.setName("A");

        ThreadB b = new ThreadB(service);

        b.setName("B");
        a.start();
        b.start();
    }
}

/*reslut:
数据写入B  1525260900544
数据写入A  1525260910545
*/

写锁互斥了,使用排他锁就线程间是互斥关系,同一时间只有一个线程可以获得写锁。

还有读写互斥和写读互斥的情况,可以灵活运用。

你可能感兴趣的:(线程Lock的使用)