【问题标题】:Thread synchronization dont work unless add print statement除非添加打印语句,否则线程同步不起作用
【发布时间】:2016-02-13 17:07:00
【问题描述】:

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

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;
}

}

【问题讨论】:

  • 您正在测试read.isEmpty(),这需要是线程安全的。
  • 我看不出这里的基本逻辑是什么,但我怀疑你可以用一个 parallelStream 替换所有这些。

标签: java multithreading synchronized


【解决方案1】:

当你这样做时

private volatile Reader read;

这意味着Reader read reference 是不稳定的。这意味着当您阅读此字段时,它的访问权限是不稳定的。但是,这并不意味着引用的对象是线程安全的。你的测试是

while (!read.isEmpty()) {

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

注意:当你写到控制台时,你间接使用了一个同步块,因为PrintStream的所有方法都是synchronized,这有一个读写障碍。

我正在编写一个程序来检查一个字符串是否包含在目录树和文本文件中

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();
            }
        });

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    相关资源
    最近更新 更多