java 可重入锁ReentrantLock和可重入读写锁ReentrantReadWriteLock范例

范例1:

package com.contoso;

public class App {

    public static void main(String[] args) throws Exception {
        ChildThread thread = new ChildThread();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                try {
                    thread.firstThread("第1个线程");
                } catch (InterruptedException ignored) {
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    thread.secondThread("第2个线程");
                } catch (InterruptedException ignored) {
                }
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        thread.finished();
    }

}
package com.contoso;

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

public class ChildThread {

    private int count = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    private void increment(String threadName) {
        for (int i = 0; i < 100; i++) {
            count++;
            System.out.println(threadName + " " + count);
        }
    }

    public void firstThread(String threadName) throws InterruptedException {
        lock.lock();
        System.out.println(threadName + " First Thread Waiting ... ... ");
        condition.await(); //releases lock
        System.out.println(threadName + " Woken up! ");
        try {
            increment(threadName);
        } finally {
            lock.unlock();
        }
    }

    public void secondThread(String threadName) throws InterruptedException {
        Thread.sleep(1000);
        lock.lock();
        System.out.println(threadName + " Calls Waiting First Thread ");
        condition.signal(); //calls waiting first thread
        try {
            increment(threadName);
        } finally {
            //should be written to unlock Thread whenever signal() is called
            lock.unlock();
        }
    }

    public void finished() {
        System.out.println("Count is: " + count);
    }
}
run:
第1个线程 First Thread Waiting ... ... 
第2个线程 Calls Waiting First Thread 
第2个线程 1
第2个线程 2
第2个线程 3
第2个线程 4
第2个线程 5
第2个线程 6
第2个线程 7
第2个线程 8
第2个线程 9
第2个线程 10
第2个线程 11
第2个线程 12
第2个线程 13
第2个线程 14
第2个线程 15
第2个线程 16
第2个线程 17
第2个线程 18
第2个线程 19
第2个线程 20
第2个线程 21
第2个线程 22
第2个线程 23
第2个线程 24
第2个线程 25
第2个线程 26
第2个线程 27
第2个线程 28
第2个线程 29
第2个线程 30
第2个线程 31
第2个线程 32
第2个线程 33
第2个线程 34
第2个线程 35
第2个线程 36
第2个线程 37
第2个线程 38
第2个线程 39
第2个线程 40
第2个线程 41
第2个线程 42
第2个线程 43
第2个线程 44
第2个线程 45
第2个线程 46
第2个线程 47
第2个线程 48
第2个线程 49
第2个线程 50
第2个线程 51
第2个线程 52
第2个线程 53
第2个线程 54
第2个线程 55
第2个线程 56
第2个线程 57
第2个线程 58
第2个线程 59
第2个线程 60
第2个线程 61
第2个线程 62
第2个线程 63
第2个线程 64
第2个线程 65
第2个线程 66
第2个线程 67
第2个线程 68
第2个线程 69
第2个线程 70
第2个线程 71
第2个线程 72
第2个线程 73
第2个线程 74
第2个线程 75
第2个线程 76
第2个线程 77
第2个线程 78
第2个线程 79
第2个线程 80
第2个线程 81
第2个线程 82
第2个线程 83
第2个线程 84
第2个线程 85
第2个线程 86
第2个线程 87
第2个线程 88
第2个线程 89
第2个线程 90
第2个线程 91
第2个线程 92
第2个线程 93
第2个线程 94
第2个线程 95
第2个线程 96
第2个线程 97
第2个线程 98
第2个线程 99
第2个线程 100
第1个线程 Woken up! 
第1个线程 101
第1个线程 102
第1个线程 103
第1个线程 104
第1个线程 105
第1个线程 106
第1个线程 107
第1个线程 108
第1个线程 109
第1个线程 110
第1个线程 111
第1个线程 112
第1个线程 113
第1个线程 114
第1个线程 115
第1个线程 116
第1个线程 117
第1个线程 118
第1个线程 119
第1个线程 120
第1个线程 121
第1个线程 122
第1个线程 123
第1个线程 124
第1个线程 125
第1个线程 126
第1个线程 127
第1个线程 128
第1个线程 129
第1个线程 130
第1个线程 131
第1个线程 132
第1个线程 133
第1个线程 134
第1个线程 135
第1个线程 136
第1个线程 137
第1个线程 138
第1个线程 139
第1个线程 140
第1个线程 141
第1个线程 142
第1个线程 143
第1个线程 144
第1个线程 145
第1个线程 146
第1个线程 147
第1个线程 148
第1个线程 149
第1个线程 150
第1个线程 151
第1个线程 152
第1个线程 153
第1个线程 154
第1个线程 155
第1个线程 156
第1个线程 157
第1个线程 158
第1个线程 159
第1个线程 160
第1个线程 161
第1个线程 162
第1个线程 163
第1个线程 164
第1个线程 165
第1个线程 166
第1个线程 167
第1个线程 168
第1个线程 169
第1个线程 170
第1个线程 171
第1个线程 172
第1个线程 173
第1个线程 174
第1个线程 175
第1个线程 176
第1个线程 177
第1个线程 178
第1个线程 179
第1个线程 180
第1个线程 181
第1个线程 182
第1个线程 183
第1个线程 184
第1个线程 185
第1个线程 186
第1个线程 187
第1个线程 188
第1个线程 189
第1个线程 190
第1个线程 191
第1个线程 192
第1个线程 193
第1个线程 194
第1个线程 195
第1个线程 196
第1个线程 197
第1个线程 198
第1个线程 199
第1个线程 200
Count is: 200
BUILD SUCCESSFUL (total time: 1 second)

范例2:

package com.contoso;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {

    private final ReentrantLock reentrantLock = new ReentrantLock();
    private boolean state = false;

    /**
     * 最简单的使用方式
     */
    public void lockMyPrinter() {
        reentrantLock.lock();
        try {
            state = !state;
            System.out.println(Thread.currentThread().getName()+" Changed State:" + state);
        } finally {
            reentrantLock.unlock();
        }
    }

    /**
     * 轮询定时获取锁 - 设置等待获取锁的时间,一旦到达指定的超时时间就放弃获取锁
     */
    public void lockMyPrinterWithTiming() throws InterruptedException {
        // 尝试在指定的超时时间获取锁 
        if (!reentrantLock.tryLock(1L, TimeUnit.SECONDS)) { 
            System.err.println("未能获得锁 - 它已经被线程 "+Thread.currentThread().getName()+" 持有");
        } else {
            try {
                System.out.println(Thread.currentThread().getName()+" 模拟阻塞计算 - 强制tryLock()失败");
                Thread.sleep(2000); 
            } finally {
                reentrantLock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        ReentrantLockExample myExample = new ReentrantLockExample();
        for (int i = 0; i < 10; i++) {
            executor.execute(() -> myExample.lockMyPrinter());
        }

        for (int i = 0; i < 20; i++) {
            executor.execute(() -> {
                try {
                    myExample.lockMyPrinterWithTiming();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}
run:
pool-1-thread-1 Changed State:true
pool-1-thread-4 Changed State:false
pool-1-thread-2 Changed State:true
pool-1-thread-4 Changed State:false
pool-1-thread-3 Changed State:true
pool-1-thread-5 Changed State:false
pool-1-thread-6 Changed State:true
pool-1-thread-7 Changed State:false
pool-1-thread-8 Changed State:true
pool-1-thread-9 Changed State:false
pool-1-thread-9 模拟阻塞计算 - 强制tryLock()失败
未能获得锁 - 它已经被线程 pool-1-thread-12 持有
未能获得锁 - 它已经被线程 pool-1-thread-11 持有
未能获得锁 - 它已经被线程 pool-1-thread-2 持有
未能获得锁 - 它已经被线程 pool-1-thread-1 持有
未能获得锁 - 它已经被线程 pool-1-thread-10 持有
未能获得锁 - 它已经被线程 pool-1-thread-13 持有
未能获得锁 - 它已经被线程 pool-1-thread-4 持有
未能获得锁 - 它已经被线程 pool-1-thread-3 持有
未能获得锁 - 它已经被线程 pool-1-thread-5 持有
未能获得锁 - 它已经被线程 pool-1-thread-6 持有
未能获得锁 - 它已经被线程 pool-1-thread-7 持有
未能获得锁 - 它已经被线程 pool-1-thread-14 持有
未能获得锁 - 它已经被线程 pool-1-thread-8 持有
未能获得锁 - 它已经被线程 pool-1-thread-18 持有
未能获得锁 - 它已经被线程 pool-1-thread-16 持有
未能获得锁 - 它已经被线程 pool-1-thread-19 持有
未能获得锁 - 它已经被线程 pool-1-thread-15 持有
未能获得锁 - 它已经被线程 pool-1-thread-20 持有
未能获得锁 - 它已经被线程 pool-1-thread-17 持有
BUILD SUCCESSFUL (total time: 2 seconds)

范例3:

package com.contoso;

import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

public class ReentrantReadWriteLockExample {

    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private String myContent = "一段很长的内容......";

    /**
     * 最简单的读模式锁
     */
    public String showContent() {
        ReadLock readLock = readWriteLock.readLock();
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+" 保持锁定时读取数据");
            return myContent;
        } finally {
            readLock.unlock();
        }
    }

    public void writeContent(String newContent) {
        WriteLock writeLock = readWriteLock.writeLock();
        writeLock.lock();
        try {
            System.err.println(Thread.currentThread().getName()+" 保持锁定时写入数据 " + newContent);
            myContent = new StringBuilder().append(myContent).append(newContent).toString();
        } finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        ReentrantReadWriteLockExample myExample = new ReentrantReadWriteLockExample();
        for (int i = 0; i < 20; i++) {
            executor.submit(() -> {
                try {
                    Thread.sleep(new Random().nextInt(10) * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(myExample.showContent());
            });
        }

        for (int i = 0; i < 5; i++) {
            executor.execute(() -> myExample.writeContent(UUID.randomUUID().toString()));
        }
        executor.shutdown();
    }
}
run:
pool-1-thread-14 保持锁定时读取数据
一段很长的内容......
pool-1-thread-3 保持锁定时读取数据
一段很长的内容......
pool-1-thread-17 保持锁定时读取数据
一段很长的内容......
pool-1-thread-19 保持锁定时读取数据
一段很长的内容......
pool-1-thread-1 保持锁定时读取数据
一段很长的内容......
pool-1-thread-10 保持锁定时读取数据
一段很长的内容......
pool-1-thread-16 保持锁定时读取数据
一段很长的内容......
pool-1-thread-20 保持锁定时读取数据
一段很长的内容......
pool-1-thread-2 保持锁定时读取数据
一段很长的内容......
pool-1-thread-13 保持锁定时读取数据
pool-1-thread-8 保持锁定时读取数据
一段很长的内容......
一段很长的内容......
pool-1-thread-6 保持锁定时读取数据
一段很长的内容......
pool-1-thread-12 保持锁定时读取数据
pool-1-thread-4 保持锁定时读取数据
一段很长的内容......
一段很长的内容......
pool-1-thread-21 保持锁定时写入数据 cb9e5ddb-8e28-4674-9eb8-193d647f77ce
pool-1-thread-24 保持锁定时写入数据 a44519a2-8c9e-41bd-a41c-c09e06a37ebf
pool-1-thread-22 保持锁定时写入数据 1348118d-2fa2-4f36-b33c-8f54eca528ea
pool-1-thread-23 保持锁定时写入数据 2e54d787-2c05-4c78-af0e-4e2956df851e
pool-1-thread-14 保持锁定时写入数据 63cec15f-6ca8-4090-8611-e3c3e040e344
pool-1-thread-5 保持锁定时读取数据
一段很长的内容......cb9e5ddb-8e28-4674-9eb8-193d647f77cea44519a2-8c9e-41bd-a41c-c09e06a37ebf1348118d-2fa2-4f36-b33c-8f54eca528ea2e54d787-2c05-4c78-af0e-4e2956df851e63cec15f-6ca8-4090-8611-e3c3e040e344
pool-1-thread-11 保持锁定时读取数据
一段很长的内容......cb9e5ddb-8e28-4674-9eb8-193d647f77cea44519a2-8c9e-41bd-a41c-c09e06a37ebf1348118d-2fa2-4f36-b33c-8f54eca528ea2e54d787-2c05-4c78-af0e-4e2956df851e63cec15f-6ca8-4090-8611-e3c3e040e344
pool-1-thread-18 保持锁定时读取数据
一段很长的内容......cb9e5ddb-8e28-4674-9eb8-193d647f77cea44519a2-8c9e-41bd-a41c-c09e06a37ebf1348118d-2fa2-4f36-b33c-8f54eca528ea2e54d787-2c05-4c78-af0e-4e2956df851e63cec15f-6ca8-4090-8611-e3c3e040e344
pool-1-thread-7 保持锁定时读取数据
一段很长的内容......cb9e5ddb-8e28-4674-9eb8-193d647f77cea44519a2-8c9e-41bd-a41c-c09e06a37ebf1348118d-2fa2-4f36-b33c-8f54eca528ea2e54d787-2c05-4c78-af0e-4e2956df851e63cec15f-6ca8-4090-8611-e3c3e040e344
pool-1-thread-9 保持锁定时读取数据
pool-1-thread-15 保持锁定时读取数据
一段很长的内容......cb9e5ddb-8e28-4674-9eb8-193d647f77cea44519a2-8c9e-41bd-a41c-c09e06a37ebf1348118d-2fa2-4f36-b33c-8f54eca528ea2e54d787-2c05-4c78-af0e-4e2956df851e63cec15f-6ca8-4090-8611-e3c3e040e344
一段很长的内容......cb9e5ddb-8e28-4674-9eb8-193d647f77cea44519a2-8c9e-41bd-a41c-c09e06a37ebf1348118d-2fa2-4f36-b33c-8f54eca528ea2e54d787-2c05-4c78-af0e-4e2956df851e63cec15f-6ca8-4090-8611-e3c3e040e344
BUILD SUCCESSFUL (total time: 1 second)

范例4:限时等待锁的使用范例

package com.myth;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
// 限时等待锁的使用范例
public class MultiThreadDemo1 implements Runnable {

    static ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            if (lock.tryLock(5, TimeUnit.SECONDS)) { // 如果超过5秒还没有获得锁,就会返回false;反之则返回true
                Thread.sleep(6000);
                System.out.println(Thread.currentThread().getName() + " get lock successfully");
            } else {
                System.out.println(Thread.currentThread().getName() + " get lock failed");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MultiThreadDemo1 instance = new MultiThreadDemo1();
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
    }
}
run:
Thread-1 get lock failed
Thread-0 get lock successfully
BUILD SUCCESSFUL (total time: 6 seconds)
package com.myth;

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

public class MultiThreadDemo2 implements Runnable {

    static ReentrantLock lock = new ReentrantLock();
    // 通过lock生成一个与之绑定的Condition对象
    static Condition condition = lock.newCondition(); 

    @Override
    public void run() {
        try {
            lock.lock();
            condition.await();  // 要求线程在Condition对象上等待
            System.out.println("Thread is going on");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MultiThreadDemo2 instance = new MultiThreadDemo2();
        Thread t1 = new Thread(instance);
        t1.start();
        Thread.sleep(2000);
        lock.lock();
        // 由主线程发出通知线程t1继续执行,告知等待在Condition上的线程可以继续执行了
        condition.signal(); 
         // 释放重入锁,如果省略lock.unlock(),即使已经唤醒了线程t1,由于线程t1无法重新获得锁,因而无法真正地继续执行
        lock.unlock();

    }

}
run:
Thread is going on
BUILD SUCCESSFUL (total time: 2 seconds)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值