多个线程向一个文件写数据

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对象,锁对象不是同一个,线程是不安全的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用多线程向同一个文件数据。但是需要注意的是,多个线程同时入同一个文件可能会导致数据错乱和文件损坏的问题。因此,在向同一个文件数据时,需要使用线程安全的方式。 以下是一个使用多线程向同一个文件数据的例子: ```java import java.io.FileWriter; import java.io.IOException; public class FileWriterThread extends Thread { private FileWriter writer; public FileWriterThread(FileWriter writer) { this.writer = writer; } @Override public void run() { synchronized (writer) { // 使用 synchronized 关键字保证线程安全 try { writer.write(Thread.currentThread().getName() + ": Hello, World!\n"); System.out.println(Thread.currentThread().getName() + " 数据成功!"); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { FileWriter writer = null; try { writer = new FileWriter("test.txt", true); // true 表示追加入 for (int i = 0; i < 10; i++) { new FileWriterThread(writer).start(); // 开启 10 个线程向同一个文件数据 } } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } } ``` 在上面的例子中,我们创建了一个 `FileWriterThread` 类,它继承了 `Thread` 类,并覆盖了 `run()` 方法。在 `run()` 方法中,我们使用 `FileWriter` 类向文件数据,并使用 `synchronized` 关键字保证线程安全。 在 `main()` 方法中,我们创建了一个 `FileWriter` 对象,并开启了 10 个线程向同一个文件数据。由于我们使用了 `synchronized` 关键字,因此多个线程可以安全地向同一个文件数据。 需要注意的是,在使用 `FileWriter` 向文件数据时,需要使用 try-catch-finally 语句块来保证资源的正确释放。在上面的例子中,我们在 `finally` 中关闭了 `FileWriter` 对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值