Frage

Ich habe ein Programm geschrieben, das Zeilen, Wörter zählt, und Zeichen in einem Text: es tut dies mit einem Gewinde. Es funktioniert großartig manchmal, aber nicht so groß, andere Zeiten. Was am Ende passiert ist die Variablen Hinweis auf die Anzahl der Wörter und Zeichen manchmal zu kurz kommt gezählt und manchmal nicht.

Es scheint mir, dass die Fäden manchmal enden, bevor sie alle Wörter oder Zeichen zählen können, die sie wollen. Ist es, weil diese Fäden außerhalb des Gültigkeitsbereichs gehen, wenn die while (true) Schleife bricht?

Ich habe den Code aus dem fadenförmigen Teil meines Problems unten enthalten:

private void countText() {
  try {
    reader = new BufferedReader(new FileReader("this.txt"));
    while (true) {
      final String line = reader.readLine();
      if(line == null) {break;}
      lines++;
      new Thread(new Runnable() {public void run() {chars += characterCounter(line);}}).start();
      new Thread(new Runnable() {public void run() {words += wordCounter(line);}}).start();
      println(line);
    }

  } catch(IOException ex) {return;}

}

(Sub Frage:.? Dies ist das erste Mal, dass ich über etwas gefragt habe und Code gepostet Ich will nicht Stackoverflow anstelle von Google und Wikipedia und mach mir Sorgen verwenden, dass dies nicht eine entsprechende Frage, die ich versuchte, die Frage allgemeiner zu machen, so dass ich nicht nur für die Hilfe bei meinem Code fragen ... aber gibt es eine andere Website, wo diese Art von Frage besser geeignet sein könnte?)

War es hilfreich?

Lösung

Ein anderes Gewinde Design würde es leichter machen, diese Art von Problem zu finden und zu beheben, und effizienter in den Kauf sein. Dies ist eine längere Antwort, aber die Zusammenfassung ist "wenn Sie Threads in Java tun, Check-out java.util.concurrent so schnell wie irgend möglich)".

Ich denke, man diesen Code ist die Multithreading-Threads zu lernen, anstatt mit Worten zu beschleunigen zu zählen, aber das ist eine sehr ineffiziente Weise Threads zu verwenden. Sie erstellen zwei Threads pro Zeile - zwei tausend Fäden für tausend Zeilendatei. ein Gewinde (in moderner JVMs) Erstellen verwendet Betriebssystemressourcen und ist in der Regel recht teuer. Wenn zwei - geschweige denn zweitausend - Fäden haben eine gemeinsame Ressource (wie Ihre chars und words Zähler) zugreifen zu können, auch die resultierende Speicherkonkurrenz verletzt Leistung

.

Vornehmen der Zählervariablen synchronized wie Chris Kimpton schlägt oder Atomic wie WMR schlägt wahrscheinlich beheben der Code, aber es wird auch die Wirkung des Anstoßes viel schlimmer machen. Ich bin mir ziemlich sicher, dass es langsamer als ein Single-Threaded-Algorithmus gehen wird.

Ich schlage vor, nur eine langlebigen Faden, die nach chars und einem für words, die jeweils mit einer Arbeitswarteschlange, an der eine neue Nummer hinzuzufügen, sieht man einreichen Jobs jedes Mal, wenn Sie wollen. Auf diese Weise nur ein Thread auf jede Variable schreibt, und wenn Sie Änderungen am Entwurf vornehmen werde es offensichtlich sein, wer für was verantwortlich ist. Es wird auch schneller sein, weil es kein Speicher Anstoß ist und Sie nicht Hunderte von Threads in einer engen Schleife zu schaffen.

Es ist auch wichtig, wenn Sie alle Zeilen in der Datei gelesen haben, auf warten für alle Threads zu beenden, bevor Sie tatsächlich aus den Werten der Zähler drucken, sonst Sie das Updates verlieren von Threads, die noch nicht fertig sind. Mit Ihrem aktuellen Design würden Sie eine große Liste von Themen aufbauen müssen Sie erstellt haben, und führen Sie durch es am Ende überprüft, dass sie alle tot sind. Mit einem Warteschlange-and-Worker-Thread-Design können Sie einfach jeden Thread sagen seine Warteschlange zu entleeren und dann warten, bis es fertig ist.

Java (von 1.5 oder höher) macht diese Art von Design ist sehr einfach zu implementieren: check out java.util.concurrent.Executors.newSingleThreadExecutor . Es macht es auch einfach später mehr Parallelität hinzufügen (richtige Verriegelung usw. vorausgesetzt), wie Sie gerade auf einen Thread-Pool wechseln, anstatt einem einzigen Thread.

Andere Tipps

Wie Chris Kimpton schon richtig darauf hingewiesen, Sie haben ein Problem mit der Aktualisierung von chars und words in verschiedenen Threads. Synchronisieren auf this wird nicht funktionieren, weil entweder this ist ein Hinweis auf den aktuellen Thread die verschiedenen Threads Mittel an verschiedenen Objekten synchronisiert. Sie könnten ein zusätzliches „Sperrobjekt“ verwenden, können Sie synchronisieren auf, aber der einfachste Weg, dies zu beheben wäre wahrscheinlich ein href zu benutzen <= "http://java.sun.com/javase/6/docs/api/java/ util / mitlaufende / Atom / AtomicInteger.html“rel = "nofollow noreferrer"> AtomicIntegers für die 2 Zähler:

AtomicInteger chars = new AtomicInteger();
...
new Thread(new Runnable() {public void run() { chars.addAndGet(characterCounter(line));}}).start();
...

Während dies wahrscheinlich Ihr Problem beheben, Sam Stoke mehr ausführliche Antwort ist völlig richtig, das ursprüngliche Design sehr ineffizient ist.

Um Ihre Frage zu beantworten, wenn ein Thread „out of scope geht“: Sie starten zwei neue Themen für jede Zeile in der Datei und alle von ihnen laufen, bis sie das Ende ihrer run() Methode erreichen. Dies ist, wenn Sie sie Daemon machen Threads) , in diesem Fall werden sie so schnell wie Daemon-Threads sind die einzigen, die noch in dieser JVM läuft verlassen.

Klingt wie eine gute Frage an mich ... Ich denke, das Problem auf die Unteilbarkeit der Zeichen in Zusammenhang stehen könnten + = und Wörter + = - mehrere Threads aufrufen könnte, dass zur gleichen Zeit - tun Sie alles tun, um sicherzustellen, dass es keine Verschachtelung.

Das heißt:

Thread 1, hat chars = 10, will 5 hinzufügen

Thread 2, hat chars = 10, will 3 hinzufügen

Thread 1 ausarbeitet neue Summe, 15

Thread 2 ausarbeitet neue Gesamt, 13

Thread 1 Sätze Zeichen bis 15

Thread 2 Sätze Zeichen bis 13.

könnte möglich sein, es sei denn, Sie synchronisiert verwenden, wenn diese Vars zu aktualisieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top