>source

두 개의 별도 스레드가있는 두 개의 개별 텍스트 파일을 읽고이를 별도의 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


  • 답변 # 1

    Solomon Slow가 주석에서 말했듯이 다중 스레드 코드를 작성하는 것은 어렵습니다. 그 말과 함께 여기에 내 의견과 제안이 있습니다.

    먼저 몇 가지 관찰 :

    텍스트는 생성자에 전달되고 필드에 저장됩니다. 그런 다음 run ()에서 getMap ()으로 전달됩니다. getMap ()은 클래스 필드 텍스트도 볼 수 있으므로 불필요합니다.

    getMap ()은지도를 반환하지만 반환 값은 run ()에서 무시됩니다.

    BufferedReader br은 getMap ()의 지역 변수가 될 수 있습니다.

    String 줄은 getMap ()에서 지역 변수가 될 수 있습니다.

    문자열 텍스트는 최종적 일 수 있습니다.

    HashMap은 생성자에서 최종 및 인스턴스화 될 수 있습니다.

    while 루프에서 replaceAll ()의 결과는 무시됩니다 (문자열은 변경할 수 없으므로 반환 값을 사용해야합니다).

    이러한 것들은 귀하의 질문을 해결하지 못하지만 클래스를 조금 더 깨끗하고 덜 변경 가능하게 만듭니다. (이 중 일부는 주관적 일 수 있습니다.)

    파서 만 보면 상태 (신규, 실행 중, 완료 등)를 알 수있는 방법이 없습니다. 사용 사례에는 그다지 중요하지 않을 수 있지만 일반적으로 다중 스레드 응용 프로그램에서 상태를 추적하고 싶습니다. 일부 부울 플래그는이를 해결할 수 있으며 원하는 경우 열거 형을 사용할 수 있습니다. 예를 들어 실수로 getMap ()을 두 번 실행하려고 시도하는 것을 방지하는 데 사용할 수 있습니다.

    이것이 스레드 (run () 사용)로만 실행되는 것을 의미한다면 getMap ()을 비공개로 만들 것입니다. 또한 구문 분석이 완료되면지도에 대한 getter 메서드를 호출 할 수 있도록 이름을 getMap () 해제하기 위해 parseFile ()로 이름을 바꿀 수도 있습니다.

    수정 된 코드 :

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

  • 이전 C에서 별 모양으로 '2'를 어떻게 인쇄합니까?
  • 다음 r - 파이프 연산자와 함께 filter () 함수를 사용하여 평균과 반올림 찾기