gpt4 book ai didi

Java 并发文件写入 - 应该会失败

转载 作者:行者123 更新时间:2023-12-01 20:25:35 25 4
gpt4 key购买 nike

我一直在测试将多个项目写入文件系统,完全预计会出现故障,其中一个线程会覆盖花药数据,或与另一项目的数据交错。

但是下面的代码意外地通过了。

为什么一个线程的数据不会覆盖另一个线程的数据?所有线程共享一个 writer。代码通过是因为 JVM 实现细节,还是真的可以预期不会混淆各个项目。

我见过一些关于多个线程写入同一文件的其他任务,但这些都是关于性能优化的。请注意,导入样式只是为了发布时的简洁。

package com.test;

import static org.junit.Assert.assertEquals;

import java.io.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;

import org.springframework.boot.CommandLineRunner;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DiskWriterApplication implements CommandLineRunner {

public static void main(String[] args) throws Exception {
new DiskWriterApplication().run(args);
}

@Override
public void run(String... args) throws Exception {
Path path = Paths.get(System.getProperty("user.home")+"/java-file.txt");
if (!Files.exists(path)) {
Files.createFile(path);
} else {
Files.delete(path);
Files.createFile(path);
}
BufferedWriter writer = Files.newBufferedWriter(path, Charset.forName("UTF-8"), StandardOpenOption.APPEND);


Thread[] threads = new Thread[4];

for (int i=0; i< 4; i++) {
threads[i] = new Thread(new DataWriter(writer, createDataItems(i)));
}

Arrays.asList(threads).forEach(Thread::start);
Arrays.asList(threads).forEach(t-> {
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
writer.close();

//Verify Lines were written correctly
ObjectMapper mapper = new ObjectMapper();
MappingIterator<Data> valueIterator = mapper.readerFor(Data.class).readValues(Files.newInputStream(path));

Set<String> uniqueItems = new HashSet<>();
int[] groupItemCount = new int[4];
while (valueIterator.hasNext())
{
Data item = valueIterator.next();

assertEquals("First Item and second Item should be equal", item.firstValue, item.secondValue);
assertEquals(10, item.innerObject.size());
assertEquals(20, item.listValues.size());

for (int i = 0 ; i< 10; i++) {
assertEquals(item.firstValue, item.innerObject.get("innerProp"+i));
}
for (int i = 0 ; i< 20; i++) {
assertEquals(item.firstValue, item.listValues.get(i));
}
uniqueItems.add(item.firstValue);
groupItemCount[item.group]++;
}

System.out.println("Got " + uniqueItems.size() + " uniqueItems");
assertEquals("Should be 4000 uniqueItems", 4000, uniqueItems.size());
assertEquals("Should be 1000 items in group[0]", 1000, groupItemCount[0]);
assertEquals("Should be 1000 items in group[1]", 1000, groupItemCount[1]);
assertEquals("Should be 1000 items in group[2]", 1000, groupItemCount[2]);
assertEquals("Should be 1000 items in group[3]", 1000, groupItemCount[3]);
}



private List<Data> createDataItems(int groupNumber) {
List<Data> items = new ArrayList<>();
for (int i =0; i<1000; i++) {
Data item = new Data();
item.group = groupNumber;
item.itemNumber = i;
item.firstValue = "{group" + groupNumber + "item" + i + "}";
item.secondValue = "{group" + groupNumber + "item" + i + "}";
for (int j =0; j< 10; j ++) {
item.addInnerProperty("innerProp"+j , "{group" + groupNumber + "item" + i + "}");
}
for (int j=0; j<20; j++) {
item.addListValue("{group" + groupNumber + "item" + i + "}");
}
items.add(item);
}
return items;
}


private class DataWriter implements Runnable {
private ArrayList<String> data;
private PrintWriter writer;

public DataWriter(BufferedWriter writer, List<Data> items) {
this.writer = new PrintWriter(writer);
this.data = new ArrayList<String>();

ObjectMapper mapper = new ObjectMapper();

for (Data i : items) {
try {
String stringValue = mapper.writeValueAsString(i);
data.add(stringValue);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


@Override
public void run() {
System.out.println("Starting batch");
data.forEach(t -> {
writer.println(t);
writer.flush();
});
System.out.println("finishing batch");
}
}

public static class Data {
public int itemNumber;
public int group;
@JsonProperty
private String firstValue;
@JsonProperty
private String secondValue;
@JsonProperty
private Map<String, String> innerObject = new HashMap<>();
@JsonProperty
private List<String> listValues = new ArrayList<>();

public void addInnerProperty(String key, String value){
this.innerObject.put(key, value);
}

public void addListValue(String value) {
this.listValues.add(value);
}

}
}

最佳答案

正如您在其他线程中看到的同样的问题: Writing a file using multiple threads in java Is writting on file using bufferwriter initialized by filewriter thread safe or not?

BufferedWriter 是同步且线程安全的

关于Java 并发文件写入 - 应该会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43919392/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com