美文网首页
线程Lock的使用

线程Lock的使用

作者: onlyHalfSoul | 来源:发表于2018-05-25 15:10 被阅读8次

    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的使用

          本文链接:https://www.haomeiwen.com/subject/cfqujftx.html