在多线程的应用场景中,解决线程安全问题使用ReentrantLock就可以(java可重入锁ReentrantLock),但是ReentrantLock是独占锁,同时只有一个线程可以获取该锁,而在写少读多的场景,显然ReentrantLock满足不了这个需求,所以ReentrantReadWriteLock应运而生。ReentrantReadWriteLock采用读写分离的策略,允许多个线程可以同时获取读锁。
ReentrantReadWriteLock() :创建 ReentrantReadWriteLock实例,随机分配使用权
ReentrantReadWriteLock(boolean fair) :创建具有公平政策的ReentrantReadWriteLock实例,在锁上等待时间最长的线程将获取锁的使用权(先来先得)。
protected Thread getOwner()
返回拥有该锁的线程,如果没有返回null,该方法是一个受保护的方法,需要使用一个类来extends ReentrantReadWriteLock类,在继承类中操作。
protected Collection<Thread> getQueuedReaderThreads()
返回一个包含可能等待获取读锁的线程的集合。
protected Collection<Thread> getQueuedThreads()
返回一个包含可能等待获取读写锁的线程的集合。
protected Collection<Thread> getQueuedWriterThreads()
返回一个包含可能等待获取写锁的线程的集合。
int getQueueLength()
返回等待获取读写锁的线程数的估计值。因为当此方法遍历内部数据结构时,线程数可能会动态更改(其他获取集合或者数量的方法都会这样)
int getReadHoldCount()
查询当前线程持有的读锁数量。
int getReadLockCount()
查询所有线程对此锁的读锁的数量。
protected Collection<Thread> getWaitingThreads(Condition condition)
返回包含这些线程的集合,这些线程可能在与写锁关联的给定条件下等待。
int getWaitQueueLength(Condition condition)
返回在与写锁关联的给定条件下等待的线程数的估计值。
int getWriteHoldCount()
查询当前线程持有的写锁数量。
boolean hasQueuedThread(Thread thread)
查询指定的线程是否等待获取读或写锁。
boolean hasQueuedThreads()
查询是否有任何线程等待获取读或写锁。
boolean hasWaiters(Condition condition)
查询是否有任何线程在与写锁关联的给定条件下等待。
boolean isFair()
如果是公平锁返回true。
boolean isWriteLocked()
查询是否有线程持有写锁。
boolean isWriteLockedByCurrentThread()
查询当前线程是否持有写锁。
ReentrantReadWriteLock.ReadLock readLock()
返回读锁。
String toString()
返回此锁的字符串,以及它的锁状态。
ReentrantReadWriteLock.WriteLock writeLock()
返回写锁。
public class TestDemo {
static String path = "C:\\tool\\1.txt";
public static void main(String[] args) throws InterruptedException {
//初始化A线程
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
FileOutputStream out = null;
try {
//线程A往文件中追加1000个A
out = new FileOutputStream(path,true);
for (int i = 0; i < 1000; i++) {
out.write("A".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
FileOutputStream out = null;
try {
//线程B往文件中追加1000个0
out = new FileOutputStream(path,true);
for (int i = 0; i < 1000; i++) {
out.write("0".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
//启动两个线程
threadA.start();
threadB.start();
}
}
0A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A000A0A0A0A0A0A0A0A0A00A0A00A0A0A0AA0A0A0A0A0A0A0A0A0A0A000A0A0A0A0A0A0A0A0A0A00A0A00A00A00A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0000A0A0A0AAAAAAAAAAAAA0AAAAA00A000AA0A0A0A0A0A00A0A0A00A0A0A0AA0A00A0A0A0A0A00A0A00A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A000A00A0A0A00A0A0A0A0A0A0A0AA0A00A0A00A0A0A0A0A0A0A00A0A0A0A0A00000000A0A0A0A0A00A0A0A0A0A0A0A000A00A00AA0A0A0A0A0A0A0A000A00A0A0A0A0A0A0A0A0A0A00000A0A0A0A0A0A0A0A0A0A00A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A000A0A0A0A0A0A0A0A0A0A0A0A0A0A00000A0AA0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AAA0A0A00A00A0A000A0A00000A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A00000000A00A0A000A0AA0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AAAAAAAAAA0A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AA0A0AAAAA0AAA0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0A0A0AA0A0A0A0A0AA0A0A0A0A0A0A00A00A0A0A0A0A0A0A0A0A0A0AA0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AA0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AA0AA0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A00A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AAAAAAAA
public class TestDemo {
static String path = "C:\\tool\\1.txt";
final static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
public static void main(String[] args) throws InterruptedException {
//初始化A线程
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
//获取文件的写锁读锁
rwl.writeLock().lock();
try {
//应为是等待了1毫秒才启动的B,这里等一下B线程启动
Thread.sleep(1);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
FileOutputStream out = null;
try {
//线程A往文件中追加1000个A
out = new FileOutputStream(path,true);
for (int i = 0; i < 1000; i++) {
out.write("A".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//释放写锁
rwl.writeLock().unlock();
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
//获取写锁,应为A已经获得,B无法再次获得,只能等A释放写锁
rwl.writeLock().lock();
FileOutputStream out = null;
try {
//线程B往文件中追加1000个0
out = new FileOutputStream(path,true);
for (int i = 0; i < 1000; i++) {
out.write("0".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//释放写锁
rwl.writeLock().unlock();
}
}
});
//启动两个线程
threadA.start();
//等一下保证A线程是先启动的,保证写进文件的是先写A,后写0,
Thread.sleep(1);
threadB.start();
}
}
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000