非常感谢。 另外请教两个问题: 1、请问为什么读不需要锁呢? 2、问什么只需要对文件加锁?假设一个action 调用 service 方法,service方法包含了对文件的读写。 那我如果只对文件加了锁,能保证读出来的内容是同步的正确的,但是,service里的内容会是正确的么? 就是说, 一个action:Action 一个service:Service Action是多线程,那Action里调用Service里方法,是创建了两块不同内存区域存储Service方法里的对象,只有当文件读写时,这两块区域才会可能有并发的交集。所以只需要对文件进行加锁,请问我理解对么? 读不需要加锁,是因为就算文件锁住了,也是可以读的,只是有可能读的数据不是最终的数据。 如果要求读的也是正确的,最好再加一个标志(如static int flag=0,未锁)标记文件是否被锁了。任意线程读或写文件之前,先判断flag(synchronized方法判断此标志位),为0,就先将其改为1,然后操作文件,操作完了改为0;为1,则等待。(LZ可以把我的lock换成flag试试)
以下是多线程读写操作文件的一个例子,如果你觉得线程太多调试麻烦,可以将线程数改小一点就可以了。 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;public class ReadWriteFileThread { private static final int READ_WIRTE_LOOP_COUNT = 10; private static final ReentrantReadWriteLock locker = new ReentrantReadWriteLock( false); private static final WriteLock writeLocker = locker.writeLock(); private static final ReadLock readLock = locker.readLock(); private static final AtomicInteger threadIndex = new AtomicInteger(1); private static final int READ_THREAD_NUMBER = 5; private static final int WRITE_THREAD_NUMBER = 5; private static final List<Thread> readThreads = new ArrayList<Thread>( READ_THREAD_NUMBER); private static final List<Thread> writeThreads = new ArrayList<Thread>( WRITE_THREAD_NUMBER); /** the specified file **/ private static final File f = new File("c:\\aa.txt"); /** the read runnable worker **/ private static final Runnable r = new ReadRunnable(f); /** the write runnable worker **/ private static final Runnable w = new WriteRunnable(f); /** * ThreadFactory is used for create the specified thread */ private static final ThreadFactory tf = new ThreadFactory() { /** * create new thread instance */ public Thread newThread(Runnable r) { final Thread t = new Thread(r); if (r instanceof ReadRunnable) { t.setName("readThread" + threadIndex.getAndIncrement()); readThreads.add(t); } else if (r instanceof WriteRunnable) { t.setName("writeThread" + threadIndex.getAndIncrement()); writeThreads.add(t); } else { throw new RuntimeException("the Runnable is not support.."); } t.setDaemon(false); return t; } }; public static void main(String[] args) { // create read thread for (int i = 0; i < READ_THREAD_NUMBER; i++) { tf.newThread(r); } // create write thread for (int i = 0; i < WRITE_THREAD_NUMBER; i++) { tf.newThread(w); } // start the following threads for (final Thread t : readThreads) { t.start(); } for (final Thread t : writeThreads) { t.start(); } } /** * ReadRunnable for read from file <br> * once a read thread is reached, the other read can be access * successfully..<br> * but the write thread will be blocked until all read thread is done <br> * * @see {@link ReentrantReadWriteLock } * @see {@link ReadLock} * * @author Administrator * */ static class ReadRunnable implements Runnable { private final File file; public ReadRunnable(final File file) { this.file = file; } public void run() { final Thread t = Thread.currentThread(); int loop = 0; while (loop++ < READ_WIRTE_LOOP_COUNT) { try { readLock.lock(); System.out.println("ready to read from file, thread name:" + t.getName()); BufferedReader br = new BufferedReader(new FileReader(file)); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (FileNotFoundException ex) { System.out.println("the file has not been created yet. " + "need to wait for write thread"); } catch (IOException ex) { ex.printStackTrace(); } finally { readLock.unlock(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * WriteRunnable for write to file <br> * once a write thread is reached, the other write can not be access <br> * and the read thread also been blocked until the write thread is done <br> * * @see {@link ReentrantReadWriteLock } * @see {@link WriteLock} * * @author Administrator * */ static class WriteRunnable implements Runnable { private final File file; public WriteRunnable(final File file) { this.file = file; } public void run() { final Thread t = Thread.currentThread(); int loop = 0; while (loop++ < READ_WIRTE_LOOP_COUNT) { try { writeLocker.lock(); System.out.println("ready to write to file, thread name:" + t.getName()); BufferedWriter br = new BufferedWriter(new FileWriter(file, true)); br.write("hello world! wirte thread Name:" + t.getName() + "\r\n"); br.flush(); } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } finally { writeLocker.unlock(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
非常感谢。 另外请教两个问题: 1、请问为什么读不需要锁呢? 2、问什么只需要对文件加锁?假设一个action 调用 service 方法,service方法包含了对文件的读写。 那我如果只对文件加了锁,能保证读出来的内容是同步的正确的,但是,service里的内容会是正确的么? 就是说, 一个action:Action 一个service:Service Action是多线程,那Action里调用Service里方法,是创建了两块不同内存区域存储Service方法里的对象,只有当文件读写时,这两块区域才会可能有并发的交集。所以只需要对文件进行加锁,请问我理解对么? 读不需要加锁,是因为就算文件锁住了,也是可以读的,只是有可能读的数据不是最终的数据。 如果要求读的也是正确的,最好再加一个标志(如static int flag=0,未锁)标记文件是否被锁了。任意线程读或写文件之前,先判断flag(synchronized方法判断此标志位),为0,就先将其改为1,然后操作文件,操作完了改为0;为1,则等待。(LZ可以把我的lock换成flag试试)谢谢oh_Maxy的热心解答。后面我还是采取在读写文件外采用synchronized控制。 不过这方面还需要进一步理解和深入。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.channels.FileLock;
public class ReadAndWriteByLock
{ public static void main(String[] args)
{
Runnable readThread = new Runnable()
{ public void run()
{
File oneFile = new File("allMyWords.txt");
readFileByLock(oneFile);
}
}; Runnable writeThread = new Runnable()
{ public void run()
{
File oneFile = new File("allMyWords.txt");
writeFileByLock(oneFile, "番茄鸡蛋我最爱!");
}
}; //异步线程测试
new Thread(writeThread).start();
new Thread(readThread).start();
} /**
* 读成功返回成功
* @param file 待操作的文件
* @return
*/
private static boolean readFileByLock(File file)
{
BufferedReader br = null;
try
{
//读操作不需要加锁
br = new BufferedReader(new InputStreamReader(new FileInputStream(file))); //对文件的读操作
String strTmp;
while ((strTmp = br.readLine()) != null)
{
System.out.println("文件读取成功:" + strTmp);
}
}
catch (FileNotFoundException e)
{
//文件不存在,返回失败
e.printStackTrace();
return false;
}
catch (IOException e)
{
//不可控的其它异常
e.printStackTrace();
return false;
}
finally
{
if (null != br)
{
try
{
br.close();
}
catch (IOException e)
{
//关闭资源失败,返回失败
e.printStackTrace();
return false;
}
}
} return true;
} /**
* 写成功返回成功
* @param file 待操作的文件
* @param myWords 追加的字符串
* @return
*/
private static boolean writeFileByLock(File file, String myWords)
{
BufferedWriter bw = null;
FileLock lock = null;
FileOutputStream fos = null;
try
{
//写操作需要锁文件
fos = new FileOutputStream(file, true);//true表示追加
int counter = 0;
try
{
lock = fos.getChannel().tryLock();
}
catch (IOException e)
{
e.printStackTrace();
}
//若锁失败,循环三次
while (lock == null)
{
counter++;
//若超过3次,直接返回失败
if (counter > 3)
{
return false;
} try
{
//等3秒后加锁
Thread.sleep(3000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
try
{
lock = fos.getChannel().tryLock();
}
catch (IOException e)
{
e.printStackTrace();
}
} bw = new BufferedWriter(new OutputStreamWriter(fos)); //对文件的写操作
bw.write(myWords);
bw.newLine();
System.out.println("文件写入成功!");
}
catch (FileNotFoundException e)
{
//文件不存在,返回失败
e.printStackTrace();
return false;
}
catch (IOException e)
{
//不可控的其它异常
e.printStackTrace();
return false;
}
finally
{
if (null != lock)
{
try
{
lock.release();
}
catch (IOException e)
{
//释放锁失败,返回失败
e.printStackTrace();
return false;
}
} if (null != bw)
{
try
{
bw.close();
}
catch (IOException e)
{
//关闭资源失败,返回失败
e.printStackTrace();
return false;
}
}
}
return true;
}
}
另外请教两个问题:
1、请问为什么读不需要锁呢?
2、问什么只需要对文件加锁?假设一个action 调用 service 方法,service方法包含了对文件的读写。
那我如果只对文件加了锁,能保证读出来的内容是同步的正确的,但是,service里的内容会是正确的么?
就是说,
一个action:Action
一个service:Service
Action是多线程,那Action里调用Service里方法,是创建了两块不同内存区域存储Service方法里的对象,只有当文件读写时,这两块区域才会可能有并发的交集。所以只需要对文件进行加锁,请问我理解对么?
另外请教两个问题:
1、请问为什么读不需要锁呢?
2、问什么只需要对文件加锁?假设一个action 调用 service 方法,service方法包含了对文件的读写。
那我如果只对文件加了锁,能保证读出来的内容是同步的正确的,但是,service里的内容会是正确的么?
就是说,
一个action:Action
一个service:Service
Action是多线程,那Action里调用Service里方法,是创建了两块不同内存区域存储Service方法里的对象,只有当文件读写时,这两块区域才会可能有并发的交集。所以只需要对文件进行加锁,请问我理解对么?
另外请教两个问题:
1、请问为什么读不需要锁呢?
2、问什么只需要对文件加锁?假设一个action 调用 service 方法,service方法包含了对文件的读写。
那我如果只对文件加了锁,能保证读出来的内容是同步的正确的,但是,service里的内容会是正确的么?
就是说,
一个action:Action
一个service:Service
Action是多线程,那Action里调用Service里方法,是创建了两块不同内存区域存储Service方法里的对象,只有当文件读写时,这两块区域才会可能有并发的交集。所以只需要对文件进行加锁,请问我理解对么?
读不需要加锁,是因为就算文件锁住了,也是可以读的,只是有可能读的数据不是最终的数据。
如果要求读的也是正确的,最好再加一个标志(如static int flag=0,未锁)标记文件是否被锁了。任意线程读或写文件之前,先判断flag(synchronized方法判断此标志位),为0,就先将其改为1,然后操作文件,操作完了改为0;为1,则等待。(LZ可以把我的lock换成flag试试)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;public class ReadWriteFileThread {
private static final int READ_WIRTE_LOOP_COUNT = 10; private static final ReentrantReadWriteLock locker = new ReentrantReadWriteLock(
false);
private static final WriteLock writeLocker = locker.writeLock();
private static final ReadLock readLock = locker.readLock();
private static final AtomicInteger threadIndex = new AtomicInteger(1); private static final int READ_THREAD_NUMBER = 5;
private static final int WRITE_THREAD_NUMBER = 5; private static final List<Thread> readThreads = new ArrayList<Thread>(
READ_THREAD_NUMBER);
private static final List<Thread> writeThreads = new ArrayList<Thread>(
WRITE_THREAD_NUMBER); /** the specified file **/
private static final File f = new File("c:\\aa.txt"); /** the read runnable worker **/
private static final Runnable r = new ReadRunnable(f); /** the write runnable worker **/
private static final Runnable w = new WriteRunnable(f); /**
* ThreadFactory is used for create the specified thread
*/
private static final ThreadFactory tf = new ThreadFactory() {
/**
* create new thread instance
*/
public Thread newThread(Runnable r) {
final Thread t = new Thread(r); if (r instanceof ReadRunnable) {
t.setName("readThread" + threadIndex.getAndIncrement());
readThreads.add(t);
} else if (r instanceof WriteRunnable) {
t.setName("writeThread" + threadIndex.getAndIncrement());
writeThreads.add(t);
} else {
throw new RuntimeException("the Runnable is not support..");
}
t.setDaemon(false);
return t;
}
}; public static void main(String[] args) {
// create read thread
for (int i = 0; i < READ_THREAD_NUMBER; i++) {
tf.newThread(r);
} // create write thread
for (int i = 0; i < WRITE_THREAD_NUMBER; i++) {
tf.newThread(w);
} // start the following threads
for (final Thread t : readThreads) {
t.start();
} for (final Thread t : writeThreads) {
t.start();
} } /**
* ReadRunnable for read from file <br>
* once a read thread is reached, the other read can be access
* successfully..<br>
* but the write thread will be blocked until all read thread is done <br>
*
* @see {@link ReentrantReadWriteLock }
* @see {@link ReadLock}
*
* @author Administrator
*
*/
static class ReadRunnable implements Runnable {
private final File file; public ReadRunnable(final File file) {
this.file = file;
} public void run() {
final Thread t = Thread.currentThread();
int loop = 0;
while (loop++ < READ_WIRTE_LOOP_COUNT) {
try {
readLock.lock();
System.out.println("ready to read from file, thread name:"
+ t.getName());
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException ex) {
System.out.println("the file has not been created yet. "
+ "need to wait for write thread");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
readLock.unlock();
} try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} /**
* WriteRunnable for write to file <br>
* once a write thread is reached, the other write can not be access <br>
* and the read thread also been blocked until the write thread is done <br>
*
* @see {@link ReentrantReadWriteLock }
* @see {@link WriteLock}
*
* @author Administrator
*
*/
static class WriteRunnable implements Runnable {
private final File file; public WriteRunnable(final File file) {
this.file = file;
} public void run() {
final Thread t = Thread.currentThread();
int loop = 0;
while (loop++ < READ_WIRTE_LOOP_COUNT) {
try {
writeLocker.lock();
System.out.println("ready to write to file, thread name:"
+ t.getName());
BufferedWriter br = new BufferedWriter(new FileWriter(file,
true));
br.write("hello world! wirte thread Name:" + t.getName()
+ "\r\n");
br.flush();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
writeLocker.unlock();
} try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
另外请教两个问题:
1、请问为什么读不需要锁呢?
2、问什么只需要对文件加锁?假设一个action 调用 service 方法,service方法包含了对文件的读写。
那我如果只对文件加了锁,能保证读出来的内容是同步的正确的,但是,service里的内容会是正确的么?
就是说,
一个action:Action
一个service:Service
Action是多线程,那Action里调用Service里方法,是创建了两块不同内存区域存储Service方法里的对象,只有当文件读写时,这两块区域才会可能有并发的交集。所以只需要对文件进行加锁,请问我理解对么?
读不需要加锁,是因为就算文件锁住了,也是可以读的,只是有可能读的数据不是最终的数据。
如果要求读的也是正确的,最好再加一个标志(如static int flag=0,未锁)标记文件是否被锁了。任意线程读或写文件之前,先判断flag(synchronized方法判断此标志位),为0,就先将其改为1,然后操作文件,操作完了改为0;为1,则等待。(LZ可以把我的lock换成flag试试)谢谢oh_Maxy的热心解答。后面我还是采取在读写文件外采用synchronized控制。
不过这方面还需要进一步理解和深入。