gpt4 book ai didi

java - 除非添加打印语句,否则线程同步不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 12:56:02 25 4
gpt4 key购买 nike

我正在制作一个程序来检查目录和文本文件树中是否包含字符串,并且我使用生产者-消费者模式。不幸的是,除非我添加打印语句,否则我的消费者线程不想停止。我尝试了一切 - 同步、使字段不稳定但仍然找不到问题。

public class Producer
extends Thread
{
private volatile Storage store;
private volatile Reader read;

Producer(Storage store, Reader read){
this.read = read;
this.store = store;
}



public void run()
{
while (!read.isEmpty()) {

String FileName = read.returnAllPaths().peek().getFileName().toString();
String item = null;
try {
item = read.returnAllPaths().take().toString();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
File currentFile = new File(item);
try (BufferedReader reader = new BufferedReader(new FileReader(currentFile))) {
String line;
while ((line = reader.readLine()) != null) {
FileAndLine current = new FileAndLine(FileName, line);
store.fillStore(current);
}
} catch (IOException e) {
e.printStackTrace();
}


}

store.setEndOfPaths(true);
}
}
public class Consumer
extends Thread
{
private volatile Storage store;
private String clue;

public Consumer(Storage store, String clue){
this.store = store;
this.clue = clue;
}

public void run()
{

FileAndLine currentLine;

while(!store.isEndOfPaths() || !store.isEmpty()){
currentLine = store.depleteStore();
System.out.println("q");
if(currentLine.line.contains(clue))
System.out.println(currentLine.FileName + ": " + currentLine.line);
}
}

}
public class Storage {
private BlockingQueue<FileAndLine> Store;
private boolean full;
private volatile boolean endOfPaths;


public Storage(){
Store = new LinkedBlockingQueue<FileAndLine>();
full = false;
}

private boolean isFull(){
return full;
}

public synchronized BlockingQueue<FileAndLine> getStore(){
return this.Store;
}

public synchronized boolean isEmpty(){
return Store.isEmpty();
}


public synchronized void setEndOfPaths(boolean set){
endOfPaths = set;
}

public synchronized boolean isEndOfPaths(){
return endOfPaths;
}

public synchronized void fillStore(FileAndLine line){
while(isFull()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Store.add(line);

full = false;
notifyAll();

if(Store.size() == 1000){
full = true;
}
}

public synchronized FileAndLine depleteStore(){

FileAndLine line;
if(endOfPaths == true && Store.isEmpty())
{
return new FileAndLine("", "");
}
while(Store.isEmpty())
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
line = new FileAndLine(Store.remove());

if(Store.size() < 1000){
full = false;
notifyAll();
}
return line;
}

}

最佳答案

当你这样做时

private volatile Reader read;

这意味着Reader读取引用是不稳定的。这意味着当您读取该字段时,它的访问是不稳定的。但是,这并不意味着引用的对象是线程安全的。您进行的测试是

while (!read.isEmpty()) {

这个测试必须是线程安全的。

注意:当您写入控制台时,您间接使用同步块(synchronized block),因为 PrintStream 的所有方法都是同步,并且这同时具有读取和写入屏障。

I am making a program that checks if a string is contained in a tree of directories and text files

String text = "looking-for";
Files.walk(Paths.get("mydir"))
.parallel()
.filter(p -> p.toFile().isFile())
.forEach(p -> {
try {
if (Files.lines(p)
.anyMatch(l -> l.contains(text)) {
System.out.println("file " + p + " contains " + text);
});
} catch (IOException e) {
e.printStackTrace();
}
});

您不需要管理将工作划分为多个线程并协调它们的所有处理,尤其是当您有一个数据处理任务时。

关于java - 除非添加打印语句,否则线程同步不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35382750/

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