难以理解线程逻辑-分配变量

8fsztsew  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(256)

我正在阅读两个带有两个独立线程的独立文本文件,然后尝试将它们分配给单独的hashmaps,并实现runnable接口。run方法调用文件解析器方法,并将其分配给类变量hashmap。如何将单独的线程分配给新的hashmap变量?我觉得我的课堂设计有一个根本的缺陷。。但任何帮助都将不胜感激。
编辑

public void run(){
this.hashMapSubject = getMap(this.text);
    this.hashMapQuery = getMap(this.text); //This just causes an overwrite of data ^^

}

public class RunnerClass {

public static void main(String[] args)  {
    Menu m = new Menu();
    m.start(); //gets user input and assigns to user subject, and then userQuery string variables.

    Thread t1 = new Thread(new Parser(m.getUserSubject()), "UserSubject");
    Thread t2 = new Thread(new Parser(m.getUserQuery()), "UserQuery");
    t1.start();
    t2.start();     

}

这是我的解析器类

public class Parser implements Runnable {
private Map<Integer, Integer> hashMap;
private String line = "";
private BufferedReader br;
private Map<Integer, Integer> hashMapSubject; //******Need to assign one to this variable
private Map<Integer, Integer> hashMapQuery; //*****Need to assign one to this variable
private String text;

public Parser(String text) { //new Thread passes user value to constructor parameter
    this.text = text;
}
public Map<Integer, Integer> getMap(String text) {

    this.hashMap = new HashMap<>();
    try {
        br = new BufferedReader(new InputStreamReader(new FileInputStream(this.text)));

        while ((line = br.readLine()) != null) {
            line.toLowerCase().replaceAll(",", "");
            String[] words = line.split("(?<=\\G.....)");

            System.out.println(Thread.currentThread().getName());

            for (String word : words) {
                int hash = word.hashCode();
                int frequency = 1;
                if (hashMap.containsKey(hash)) {
                    frequency += hashMap.get(hash);
                }
                hashMap.put(hash, frequency);

            }           
        }           
    }
         catch (IOException e) {
        System.out.println("File not found");
        e.printStackTrace();
    }

    return hashMap;
}
@Override //**************************************
public void run() {
    getMap(this.text);

    //********************************************
} //run method here getsMap() for each thread

}
输出的一个例子:我看到两个线程都在执行它们的任务,但如何将数据提取到新变量中却让我感到困惑

Enter subject...
Enter Query...
Processing...
UserSubject
UserQuery
UserSubject
UserQuery 
UserSubject //continues like this until termination
lokaqttq

lokaqttq1#

正如solomonslow在评论中所说,编写多线程代码很难。话虽如此,以下是我的意见和建议。
首先是一些观察:
文本被传递给构造函数并存储在字段中。然后将其从run()传递到getmap()。这是不必要的,因为getmap()还可以看到类字段文本。
getmap()返回Map,但在run()中忽略返回值。
bufferedreader br可以是getmap()中的局部变量。
字符串行可以是getmap()中的局部变量。
字符串文本可能是最终文本
hashmap可以是最终的,并在构造函数中示例化
在while循环中,replaceall()的结果被忽略(字符串是不可变的,您需要使用返回值)
这些东西并不能解决你的问题,但会让这个类更干净,更不易变(有些可能是主观的。)
只看解析器无法知道它的状态(new、running、finished等)。虽然它对您的用例可能不是很重要,但我通常喜欢跟踪多线程应用程序中的状态。一些布尔标志可以解决这个问题,如果需要,可以使用枚举。例如,这可以用来防止意外尝试运行getmap()两次。
如果这意味着只能作为线程运行(使用run()),我会将getmap()设为私有。我还可以考虑将其重命名为parsefile(),以便在解析完成后释放getter方法的getmap()名称。
修改代码:

public class Parser implements Runnable {
    private final Map<Integer, Integer> hashMap;
    private final String text;

    private enum ParserState {NEW, RUNNING, DONE}

    private ParserState state;

    public Parser(String text) { //new Thread passes user value to constructor parameter
        this.text = text;
        this.hashMap = new HashMap<>();
        this.state = ParserState.NEW;
    }

    private void processFile() {
        if (state != ParserState.NEW) {
            return;
        }

        this.state = ParserState.RUNNING;
        String line = "";

        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(this.text)));

            while ((line = br.readLine()) != null) {
                line = line.toLowerCase().replaceAll(",", ""); // Don't forget to use the replaceAll() return value
                String[] words = line.split("(?<=\\G.....)");

                System.out.println(Thread.currentThread().getName());

                for (String word : words) {
                    int hash = word.hashCode();
                    int frequency = 1;
                    if (hashMap.containsKey(hash)) {
                        frequency += hashMap.get(hash);
                    }
                    hashMap.put(hash, frequency);

                }
            }
        } catch (IOException e) {
            System.out.println("File not found");
            e.printStackTrace();
        }
        this.state = ParserState.DONE;
    }

    public boolean isDone() {
        return state == ParserState.DONE;
    }

    public Map<Integer, Integer> getMap() {
        if (state != ParserState.DONE) {
            throw new IllegalStateException();
        }
        return hashMap;
    }

    @Override //**************************************
    public void run() {
        processFile();
    }

    //********************************************
} //run method here getsMap() for each thread

跑步者:

public class RunnerClass {

    public static void main(String[] args)  {
        Menu m = new Menu();
        m.start(); //gets user input and assigns to user subject, and then userQuery string variables.

        Parser userSubjectParser = new Parser(m.getUserSubject());
        Parser userQueryParser = new Parser(m.getUserQuery());

        Thread t1 = new Thread(userSubjectParser, "UserSubject");
        Thread t2 = new Thread(userQueryParser, "UserQuery");
        t1.start();
        t2.start();

        // Wait until both threads are finished

        Map<Integer, Integer> hashMapSubject = userSubjectParser.getMap();
        Map<Integer, Integer> hashMapQuery = userQueryParser.getMap();

    }
}

相关问题