package com.bean;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* 多个线程向一个文件写数据
*/
public class ThreadDemo
{
static Write write = new Write();
public static void main(String[] args)
{
String path = "C:\\Users\\DOG\\Desktop\\aa.txt";
String message1 = Thread.currentThread().getName()+":hello";
String message2 = "world";
//创建100个线程
for(int i=0;i<100;i++){
new Thread(new Runnable(){
@Override
public void run(){
write.write(path, message1,message2);
}
}).start();
}
}
}
class Write
{
public synchronized void write(String path,String message1,String message2){
FileWriter writer = null;
try {
File file = new File(path);
writer = new FileWriter(file,true);//追加写入
writer.write(message1);
Thread.sleep(100);
writer.write(message2+"\n");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if(writer != null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
写到文件里如下:
main:helloworld
main:helloworld
main:helloworld
main:helloworld
main:helloworld
main:helloworld
main:helloworld
main:helloworld
main:helloworld
main:helloworld
...
可以看出代码是线程安全的,没有出现写乱的情况,但是把Write类的write方法上的synchronized关键字去掉,发现写入文件里也是和没去掉synchronized关键字时一样的效果,跟踪java.io.FileWriter的write方法:
public void write(String str) throws IOException {
write(str, 0, str.length());
}
public void write(String str, int off, int len) throws IOException {
synchronized (lock) {
char cbuf[];
if (len <= WRITE_BUFFER_SIZE) {
if (writeBuffer == null) {
writeBuffer = new char[WRITE_BUFFER_SIZE];
}
cbuf = writeBuffer;
} else { // Don't permanently allocate very large buffers.
cbuf = new char[len];
}
str.getChars(off, (off + len), cbuf, 0);
write(cbuf, 0, len);
}
}
发现write方法里有synchronized代码块,锁为当前对象(lock),因为写入文件的操作只new了一个FileWriter对象(new FileWriter(file,true);),所以所有的线程竞争同一把锁,自然也就是线程安全的了,但是如果写的操作new了多个FileWriter对象,就会出现写乱的情况,因为不是竞争的同一把锁,如下:
class Write
{
public void write(String path,String message1,String message2){
FileWriter writer1 = null;
FileWriter writer2 = null;
try {
File file = new File(path);
//new两个FileWriter对象
writer1 = new FileWriter(file,true);//追加写入
writer2 = new FileWriter(file,true);//追加写入
writer1.write(message1);
Thread.sleep(100);
writer2.write(message2+"\n");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if(writer1 != null){
try {
writer1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(writer2 != null){
try {
writer2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
写到文件里如下:
main:hellomain:helloworld
world
main:hellomain:helloworld
world
main:hellomain:hellomain:helloworld
world
world
main:hellomain:hellomain:hellomain:hellomain:hellomain:hellomain:hellomain:hellomain:helloworld
world
world
world
main:hellomain:hellomain:helloworld
...
可以发现文件写乱了,线程不安全,因为竞争的不是同一把锁对象。如果在Write类的write方法上加上synchronized关键字,可以发现写入不乱了,因为这个synchronized关键字的锁对象为main方法里的write对象(static Write write = new Write();),锁为同一把锁,线程安全。但是每个线程new一个Write对象,发现线程是不安全的,代码和结果如下:
package com.bean;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* 多个线程向一个文件写数据
*/
public class ThreadDemo
{
// static Write write = new Write();
public static void main(String[] args)
{
String path = "C:\\Users\\DOG\\Desktop\\aa.txt";
String message1 = Thread.currentThread().getName()+":hello";
String message2 = "world";
//创建100个线程
for(int i=0;i<100;i++){
new Thread(new Runnable(){
@Override
public void run(){
new Write().write(path, message1,message2);
}
}).start();
}
}
}
class Write
{
public synchronized void write(String path,String message1,String message2){
FileWriter writer1 = null;
FileWriter writer2 = null;
try {
File file = new File(path);
//new两个FileWriter对象
writer1 = new FileWriter(file,true);//追加写入
writer2 = new FileWriter(file,true);//追加写入
writer1.write(message1);
Thread.sleep(100);
writer2.write(message2+"\n");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if(writer1 != null){
try {
writer1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(writer2 != null){
try {
writer2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
写到文件里如下:
main:hellomain:hellomain:hellomain:hellomain:hellomain:helloworld
world
world
world
world
world
main:hellomain:helloworld
world
main:hellomain:hellomain:helloworld
world
main:helloworld
world
main:helloworld
main:hellomain:hellomain:helloworld
...
因为多个线程调用Write类的write方法时,每个线程用了一个Write对象,锁对象不是同一个,线程是不安全的。