FileLock是是进程级别的锁,可以保证不同的进程来对文件读写互斥,进程一般也就是指一个main函数对应一个jvm。在windows下,进程锁存在,但是在linux下,进程锁不存在,也就是说不同进程可以同时读写一个文件。
读文件:
//读文件函数
package testjzx;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Calendar;
public class Read2 {
public static void read() {
try {//读取文件
Calendar calstart = Calendar.getInstance();
//Thread.sleep(3);
File file = new File("D:/1_1_1_1_1_0.json");
FileInputStream fis = new FileInputStream(file);
FileChannel fcin = fis.getChannel();
FileLock flin = null;
while (true) {
flin = fcin.tryLock(0, Long.MAX_VALUE, true);
if (flin != null) {
break;
} else {
System.out.println("有写线程正在操作该文件,当前线程休眠10毫秒");
Thread.sleep(10);
continue;
}
}
System.out.println("开始读文件!");
InputStreamReader inputStreamReader = new InputStreamReader(fis, "UTF-8");
BufferedReader reader = new BufferedReader(inputStreamReader);
StringBuffer sb = new StringBuffer();
String tempString = null;
while ((tempString = reader.readLine()) != null) {//按行读取
sb.append(tempString);
}
System.out.println(sb.toString());
System.out.println("读文件结束" );
Calendar calend = Calendar.getInstance();
System.out.println("读文件共花了" + (calend.getTimeInMillis() - calstart.getTimeInMillis()) + "毫秒");
reader.close();
// flin.release();//释放锁有两种方式,关闭通道,或者调用lock的release()方法。
fcin.close();
fis.close();
fis = null;
//Thread.sleep(10);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
写文件:
package testjzx;
import com.alibaba.fastjson.JSONArray;
import utils.DataAcquisition;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Calendar;
import java.util.List;
import static agent.eventProcessor.ParameterConfigTest.getAllConfig;
public class Write2 {
public static int flag=0;
public static void write()
{
try {
Calendar calstart = Calendar.getInstance();
File file = new File("D:/1_1_1_1_1_0.json");
if (!file.exists())
file.createNewFile();
//对该文件加锁
FileOutputStream out = new FileOutputStream(file);
FileChannel fcout = out.getChannel();
FileLock flout = null;
while (true) {
flout = fcout.tryLock();
if (flout != null) {
break;
} else {
System.out.println("有读线程正在操作该文件,当前线程休眠10毫秒");
Thread.sleep(10);
continue;
}
}
System.out.println("开始写文件!");
flag++;
if(flag>2)
flag=flag-3;
List<String> config = getAllConfig(flag);
JSONArray datamap = DataAcquisition.getQueryDatamap(config);
String jsonstring=datamap.toJSONString();
System.out.println("文件内容:"+jsonstring);
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write(jsonstring);
bufferedWriter.flush();
bufferedWriter.close();
System.out.println("写文件结束!");
Calendar calend = Calendar.getInstance();
System.out.println("写文件共花了" + (calend.getTimeInMillis() - calstart.getTimeInMillis()) + "毫秒");
//flout.release();//释放锁有两种方式,关闭通道,或者调用lock的release()方法。
fcout.close();
out.close();
out = null;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
读线程:
package testjzx;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Calendar;
public class Read extends Thread{
public void run() {
while (true) {
try {
Read2.read();
sleep(10);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
写线程:
package testjzx;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Calendar;
public class Write extends Thread{
public void run() {
while (true) {
try {
Write2.write();
sleep(10);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
然后用两个main函数(两个线程)分别开启读写线程即可。
现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写的操作了。
针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁,描述如下:
线程进入读锁的前提条件:
没有其他线程的写锁,
没有写请求或者有写请求,但调用线程和持有锁的线程是同一个。
线程进入写锁的前提条件:
没有其他线程的读锁
没有其他线程的写锁
读写文件:
package testjzx.testjzx2;
import com.alibaba.fastjson.JSONArray;
import utils.DataAcquisition;
import java.io.*;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static agent.eventProcessor.ParameterConfigTest.getAllConfig;
public class Service {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public static int flag=0;
public void read() {
try {
try {
lock.readLock().lock();
System.out.println("获取读锁" + Thread.currentThread().getName());
Calendar calstart = Calendar.getInstance();
File file = new File("D:/1_1_1_1_1_0.json");
FileInputStream fis = new FileInputStream(file);
System.out.println("开始读文件!");
InputStreamReader inputStreamReader = new InputStreamReader(fis, "UTF-8");
BufferedReader reader = new BufferedReader(inputStreamReader);
StringBuffer sb = new StringBuffer();
String tempString = null;
while ((tempString = reader.readLine()) != null) {//按行读取
sb.append(tempString);
}
System.out.println("文件内容:"+sb.toString());
Calendar calend = Calendar.getInstance();
System.out.println("读文件共花了" + (calend.getTimeInMillis() - calstart.getTimeInMillis()) + "毫秒");
} finally {
lock.readLock().unlock();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("获取写锁" + Thread.currentThread().getName());
Calendar calstart = Calendar.getInstance();
File file = new File("D:/1_1_1_1_1_0.json");
if (!file.exists())
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
System.out.println("开始写文件!");
flag++;
if(flag>2)
flag=flag-3;
List<String> config = getAllConfig(flag);
JSONArray datamap = DataAcquisition.getQueryDatamap(config);
String jsonstring=datamap.toJSONString();
System.out.println("文件内容:"+jsonstring);
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write(jsonstring);
bufferedWriter.flush();
bufferedWriter.close();
System.out.println("写文件结束!");
Calendar calend = Calendar.getInstance();
System.out.println("写文件共花了" + (calend.getTimeInMillis() - calstart.getTimeInMillis()) + "毫秒");
} finally {
lock.writeLock().unlock();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
读线程:
package testjzx.testjzx2;
import testjzx.Read2;
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service)
{
this.service=service;
}
public void run() {
while (true) {
try {
service.read();
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
写线程
package testjzx.testjzx2;
public class ThreadB extends Thread{
private Service service;
public ThreadB(Service service)
{
this.service=service;
}
public void run() {
while (true) {
try {
service.write();
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程级别的锁,在一个main函数开启两个线程即可
package testjzx.testjzx2;
public class Test {
public static void main(String[] args)throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}