Mein Freund hat mich gebeten, mir zu helfen, ein Programm zu schreiben, um Daten aus einem Textdokument in eine Oracle -Datenbank zu importieren. Es ist technisch nicht schwierig. Das Format des Dokuments ist festgelegt. Solange die entsprechende Feldanalyse in der Datenbank ausreicht, liegt der Schlüssel in der Leistung.
Das Datenvolumen ist groß und Millionen von Datensätzen. In Anbetracht der Tatsache, dass Sie die gleichzeitige Ausführung von Multi-Thread verwenden müssen, möchte ich während des Schreibprozesses auf Probleme stoßen, ich möchte die Gesamtzeit, die für alle Kinderprozesse nach Abschluss der Ausführung aufgewendet wird, zählen. Notieren Sie die aktuelle Zeit, bevor der erste Kinderprozess erstellt wird. Verwenden Sie System.currentTimemillis (), um die aktuelle Zeit nach Abschluss des letzten Kinderprozesses aufzuzeichnen. Der Zeitunterschied, der zweimal durch Subtraktion erhalten wird, ist die Gesamtzeit. Der Code ist wie folgt
long tstart = system.currentTimemillis (); System.out.println (Thread.currentThread (). GetName () + "start"); // Drucken Sie die Startmarke für (int ii = 0; ii <threadnum; ii ++) {// Open Threads Runnable r = new Runnable () {@Override öffentlich void run () {). // etwas tun ... ... System.out.println (Thread.currentThread (). GetName () + "Ende"); }} Thread t = neuer Thread (r); t.start (); } System.out.println (Thread.currentThread (). GetName () + "Ende."); // drucken end -tag long tend = system.currentTimemillis (); System.out.println ("Gesamtzeit:" + (tendieren - tstart) + "Millionen"); Das Ergebnis ist, dass die vom Haupt -Thread zum Drucken der Gesamtzeit verwendeten Aussagen fast so ausgeführt werden, dass der für die Schleife endet. Der Grund dafür ist, dass alle untergeordneten Threads gleichzeitig ausgeführt werden, und der Haupt -Thread wird auch ausgeführt, wenn sie ausgeführt werden, was eine Frage aufwirft: Wie man den Haupt -Thread auf alle ausführenden Kinderfäden warten lassen. Ich habe versucht, T.Join () nach dem Start jedes untergeordneten Threads hinzuzufügen, und das Ergebnis ist, dass alle Threads nacheinander ausführen, was die Bedeutung der Parallelität verliert, was offensichtlich nicht das ist, was ich will.
Google hat seit langer Zeit keine Lösung online mehr gefunden. Hat niemand jemals ein solches Bedürfnis gestoßen? Oder ist dieses Problem zu einfach? Wu Nai musste selbst an eine Lösung denken ...
Schließlich ist es meine Lösung, eine ImportThread -Klasse zu passen, die von java.lang.thread überlastet, die Run () -Methode überlastet und eine Listeneigenschaft verwendet, um alle generierten Threads zu speichern. Auf diese Weise werden Sie, solange Sie beurteilen, ob die Liste leer ist, wissen, ob es noch keine Kinderfäden gibt, die noch nicht ausgeführt wurden. Der Klassencode lautet wie folgt:
öffentliche Klasse ImportThread erweitert Thread {private statische Liste <Thread> runningThreads = new ArrayList <Thread> (); public ImportThread () {} @Override public void run () {Registrierung (this); // Register System.out.println (Thread.CurrentThread (). "Ende."); // Drucken Sie das End -Tag} public void Registrierung (Thread t) {synchronized (RunningThreads) {RunningThreads.add (t); }} public void unregist (thread t) {synchronized (runningThreads) {synchronized (runningThreads) {runnioThreads.remove (t); }} public static boolean ashreadrunning () {return (RunningThreads.Size ()> 0); // Durch Beurteilung, ob RunningThreads leer ist, können Sie wissen, ob es noch Threads gibt, die nicht ausgeführt wurden}}}} Code im Haupt -Thread:
long tstart = system.currentTimemillis (); System.out.println (Thread.currentThread (). GetName ()+"start"); // Drucken Sie die Startmarke für (int ii = 0; ii <threadnum; ii ++) {// Threads Thread t = new ImportThread (); t.start (); } while (true) {// Warten auf alle untergeordneten Threads, um die Ausführung zu vervollständigen, wenn (! ImportThread.Hasthreadrunning ()) {Break; } Thread.sleep (500); } System.out.println (Thread.currentThread (). GetName () + "Ende."); // drucken end -tag long tend = system.currentTimemillis (); System.out.println ("Gesamtzeit:" + (tendieren - tstart) + "Millionen");Das Druckergebnis ist:
Hauptstart
Thread-1 beginnt ...
Thread-5 beginnt ...
Thread-0 beginnt ...
Thread-2 beginnt ...
Thread-3 beginnt ...
Thread-4 beginnt ...
Thread-5 endet.
Thread-4 endet.
Thread-2 endet.
Thread-0 endet.
Thread-3 endet.
Thread-1 endet.
Das Ende von Main.
Gesamtzeit: 20860 Millionen
Sie können sehen, dass der Haupt -Thread nur die Ausführung beginnt, nachdem alle untergeordneten Threads ausgeführt wurden.
========================================================================= ==========================================================================
Die obige Methode hat eine versteckte Gefahr: Wenn Thread 1 beginnt und endet und andere Threads noch nicht begonnen haben, ist die Größe von Running Threads auch 0, der Haupt -Thread wird der Meinung, dass alle Threads ausgeführt wurden. Die Lösung besteht darin, Listentyp-Running-Threads durch einen nicht einfachen Zähler zu ersetzen, und der Zählerwert sollte vor der Erstellung von Thread eingestellt werden.
MyCountdown -Klasse
öffentliche Klasse MyCountdown {private int count; public mycountdown (int count) {this.count = count; } public synchronisierte void Countdown () {count--; } public synchronisierte boolean hasNext () {return (count> 0); } public int getCount () {return count; } public void setCount (int count) {this.count = count; }} ImportThread -Klasse
öffentliche Klasse ImportThread erweitert Thread {private mycountdown c; public importThread (mycountdown c) {this.c = c; } @Override public void run () {System.out.println (thread.currentthread (). GetName () + "start ..."); // Drucken Sie den Startmarker // etwas countdown (); // Timer minus 1 system.out.println (thread.current thread (). Endmarke}} Im Hauptfaden
System.out.println (Thread.currentThread (). GetName ()+"start"); // Drucken Sie den Start -Tag myCountdown c = neuer MyCountdown (Threadnum); // Initialisieren Sie Countdown für (int II = 0; t.start (); } while (true) {// darauf warten, dass alle untergeordneten Threads ausgeführt werden, wenn (! c.hasnext ()) brechen; } System.out.println (Thread.currentThread (). GetName () + "Ende."); // Drucken Sie das Endmarke ausDruckergebnis:
Hauptstart
Thread-2 beginnt ...
Thread-1 beginnt ...
Thread-0 beginnt ...
Thread-3 beginnt ...
Thread-5 beginnt ...
Thread-4 beginnt ...
Thread-5 endet. 5 weitere Themen
Thread-1 endet. Es gibt 4 weitere Themen
Thread-4 endet. Es gibt 3 weitere Themen
Thread-2 endet. 2 weitere Fäden
Thread-3 endet. 1 Thread ist immer noch da
Thread-0 endet. Es sind 0 Threads übrig
Das Ende von Main.
Einfacherer Weg: Verwenden Sie java.util.concurrent
ImportThread -Klasse
public class ImportThread erweitert Thread {private Countdownlatch -ThreadSsignal; public importThread (Countdownlatch threadsSsignal) {this.threadsSignal = threadsSsignal; } @Override public void run () {System.out.println (Thread.currentThread (). GetName () + "start ..."); // etwas threadssignal.countdown (); // Der Zähler wird am Ende des Thread -Systems um 1 reduziert. }} Im Hauptfaden
CountdownLatch -Threadsignal = new Countdownlatch (Threadnum); // Initialisieren Sie Countdown für (int ii = 0; ii <threadnum; ii ++) {// Threads endgültig iterator <string> itt = it.get (ii); Thread T = neuer ImportThread (ITT, SQL, Threadsignal); t.start (); } threadsignal.aawait (); // Warten auf alle untergeordneten Threads, um Ausführungssystem.out.println (Thread.currentThread (). GetName () + "End."); // Drucken Sie die Endmarke ausDruckergebnis:
Hauptstart
Thread-1 beginnt ...
Thread-0 beginnt ...
Thread-2 beginnt ...
Thread-3 beginnt ...
Thread-4 beginnt ...
Thread-5 beginnt ...
Thread-0 endet. 5 weitere Themen
Thread-1 endet. Es gibt 4 weitere Themen
Thread-4 endet. Es gibt 3 weitere Themen
Thread-2 endet. 2 weitere Fäden
Thread-5 endet. 1 Thread ist immer noch da
Thread-3 endet. Es sind 0 Threads übrig
Das Ende von Main.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.