悲观锁:

1、当一个线程访问这个数据的时候,悲观锁会把这个数据给锁住,不被其他线程所访问,直到这个线程完成了对数据的提交后,其他线程才能够访问或者操作这个数据。

2、悲观锁具有强烈的独占和排他特性。

悲观锁例子:

package com.what21.thread;
import java.io.File;
import java.io.RandomAccessFile;
public class PessimisticLockMain {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 1. 文件
File file = new File("D:/PessimisticLock.txt");
if (!file.exists()){
file.createNewFile();
}
// 2. 文件流
RandomAccessFile rAccess = new RandomAccessFile(file, "rw");
// 3. 线程执行
CloseFileThread cfThread = new CloseFileThread(rAccess);
AccessFileThread t1 = new AccessFileThread("线程一",rAccess);
t1.start();
AccessFileThread t2 = new AccessFileThread("线程二",rAccess);
t2.start();
AccessFileThread t3 = new AccessFileThread("线程三",rAccess);
t3.start();
AccessFileThread t4 = new AccessFileThread("线程四",rAccess);
t4.start();
AccessFileThread t5 = new AccessFileThread("线程五",rAccess);
t5.start();
AccessFileThread t6 = new AccessFileThread("线程六",rAccess);
t6.start();
AccessFileThread t7 = new AccessFileThread("线程七",rAccess);
t7.start();
AccessFileThread t8 = new AccessFileThread("线程八",rAccess);
t8.start();
// 4. 关闭文件流
cfThread.start();
}
/**
* 线程休息
*
* @param millis
*/
public static void threadSleep(long millis){
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.what21.thread;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class AccessFileThread extends Thread{
private String name;
private RandomAccessFile rAccessFile;
public AccessFileThread(String name,RandomAccessFile rAccessFile){
super.setName(name);
this.name = name;
this.rAccessFile = rAccessFile;
CloseFileThread.put(this);
}
@Override
public void run() {
try {
FileChannel fileChannel = rAccessFile.getChannel();
// 1. 判断当前文件是否有文件锁
FileLock flout = null;
int count = 0;
while(true){
count ++;
try {
PessimisticLockMain.threadSleep(2*10);
// 是否有文件锁,如果有文件锁,咋抛出异常
flout = fileChannel.tryLock();
break;
} catch (Exception e) {
String message = "[" + name + "]有其他线程正在操作该文件,";
message = message + "当前线程"+count+"次等待";
System.out.println(message);
}
}
// 2. 如果没有文件锁,就操作文件,写入文件内容
AccessFileThread.writeFile(fileChannel,"[" + name + "]已完成\r\n");
PessimisticLockMain.threadSleep(10);
// 3. 写入内容完成后,释放锁
flout.release();
CloseFileThread.remove(this);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param fileChannel
* @param text
* @throws IOException
*/
private static void writeFile(FileChannel fileChannel,String text) throws IOException{
byte[] bytes = text.getBytes("UTF-8");
ByteBuffer buffer = ByteBuffer.wrap(bytes);
fileChannel.write(buffer);
}
}
package com.what21.thread;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Hashtable;
import java.util.Map;
public class CloseFileThread extends Thread {
public static Map threadMap = new Hashtable();
private RandomAccessFile rAccessFile;
public CloseFileThread(RandomAccessFile rAccessFile){
this.rAccessFile = rAccessFile;
}
@Override
public void run() {
while(true){
if(threadMap.size()<=0){
if(rAccessFile!=null){
try {
rAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
rAccessFile = null;
}
System.out.println("[关闭文件线程]关闭文件流");
break;
}
PessimisticLockMain.threadSleep(2*100);
}
}
/**
* @param thread
*/
public static void put(Thread thread){
threadMap.put(thread.getName(), thread);
}
/**
* @param thread
*/
public static void remove(Thread thread){
threadMap.remove(thread.getName());
}
}

Console输出:

[线程六]有其他线程正在操作该文件,当前线程1次等待

[线程四]有其他线程正在操作该文件,当前线程1次等待

[线程三]有其他线程正在操作该文件,当前线程1次等待

[线程八]有其他线程正在操作该文件,当前线程1次等待

[线程七]有其他线程正在操作该文件,当前线程1次等待

[线程五]有其他线程正在操作该文件,当前线程1次等待

[线程二]有其他线程正在操作该文件,当前线程1次等待

[线程三]有其他线程正在操作该文件,当前线程2次等待

[线程七]有其他线程正在操作该文件,当前线程2次等待

[线程八]有其他线程正在操作该文件,当前线程2次等待

[线程四]有其他线程正在操作该文件,当前线程2次等待

[线程五]有其他线程正在操作该文件,当前线程2次等待

[线程二]有其他线程正在操作该文件,当前线程2次等待

[线程七]有其他线程正在操作该文件,当前线程3次等待

[线程四]有其他线程正在操作该文件,当前线程3次等待

[线程八]有其他线程正在操作该文件,当前线程3次等待

[线程五]有其他线程正在操作该文件,当前线程3次等待

[线程二]有其他线程正在操作该文件,当前线程3次等待

[线程八]有其他线程正在操作该文件,当前线程4次等待

[线程五]有其他线程正在操作该文件,当前线程4次等待

[线程七]有其他线程正在操作该文件,当前线程4次等待

[线程二]有其他线程正在操作该文件,当前线程4次等待

[线程八]有其他线程正在操作该文件,当前线程5次等待

[线程七]有其他线程正在操作该文件,当前线程5次等待

[线程二]有其他线程正在操作该文件,当前线程5次等待

[线程七]有其他线程正在操作该文件,当前线程6次等待

[线程二]有其他线程正在操作该文件,当前线程6次等待

[线程二]有其他线程正在操作该文件,当前线程7次等待

[关闭文件线程]关闭文件流

文件输出(PessimisticLock.txt):

[线程一]已完成

[线程六]已完成

[线程三]已完成

[线程四]已完成

[线程五]已完成

[线程八]已完成

[线程七]已完成

[线程二]已完成

总结:

当线程访问文件时,先得到访问资源的线程会使用悲观锁给锁住,直到写入数据完成,释放锁。