Meu amigo me pediu para me ajudar a escrever um programa para importar dados de um documento de texto para um banco de dados Oracle. Não é tecnicamente difícil. O formato do documento é corrigido. Enquanto a análise de campo correspondente no banco de dados for suficiente, a chave está no desempenho.
O volume de dados é grande e milhões de registros. Portanto, considerando que você precisa usar a execução simultânea de vários thread e encontrar problemas durante o processo de escrita, quero contar o tempo total gasto em todos os processos infantis após a conclusão da execução. Registre o horário atual antes do primeiro processo infantil ser criado. Use System.CurrentTimemillis () para registrar o horário atual após a conclusão do último processo infantil. A diferença de tempo obtida por subtração duas vezes é o tempo total. O código é o seguinte
tstart longo = system.currenttimemillis (); System.out.println (thread.currentThread (). GetName () + "start"); // imprima a marca de partida para (int ii; // Faça algo ... ... System.out.println (thread.currentThread (). GetName () + "end."); }} Thread t = novo thread (r); t.start (); } System.out.println (Thread.currentThread (). GetName () + "end."); // Print End Tag Long tend = System.currenttimemillis (); System.out.println ("Tempo total:" + (tend - tstart) + "milhões"); O resultado é que as declarações usadas pelo encadeamento principal para imprimir o tempo total são executadas quase no momento em que o loop termina. O motivo é que todos os threads infantis são executados simultaneamente, e o tópico principal também está em execução quando executam, o que levanta uma pergunta: como "fazer com que o tópico principal aguarde que todos os threads infantis sejam executados". Tentei adicionar T.Join () após o início de cada encadeamento infantil, e o resultado é que todos os threads são executados sequencialmente, o que perde o significado da simultaneidade, o que obviamente não é o que eu quero.
O Google não encontra uma solução online há muito tempo. Ninguém nunca encontrou tal necessidade? Ou esse problema é muito simples? Wu Nai teve que pensar em uma solução ...
Finalmente, minha solução é personalizar uma classe de importação herda do java.lang.thread, sobrecarregar o método run () e usar uma propriedade de lista para salvar todos os threads gerados. Dessa forma, desde que você julgue se a lista está vazia, você saberá se ainda existem tópicos infantis que não foram executados. O código de classe é o seguinte:
classe pública ImportThread estende o thread {Private Static List <Thread> RunningThreads = new ArrayList <Thread> (); public importThread () {} @Override public void run () {Registration (this); // Register System.out.println (thread.currentThread (). getName () + "start ..."); // imprima o start Marker // faz algo ... UNREGIST (this); "end."); // Imprima a etiqueta final} public void Registration (Thread T) {Sincronized (RunningThreads) {Runningthreads.add (t); }} public void unregist (thread t) {sincronizado (runningthreads) {sincronizado (runningthreads) {runningthreads.remove (t); }} public static boolean hasthreadRunning () {return (runningthreads.size ()> 0); // Ao julgar se o rankingthreads está vazio, você pode saber se ainda existem tópicos que não foram executados}}} Código no tópico principal:
tstart longo = system.currenttimemillis (); System.out.println (thread.currentThread (). GetName ()+"start"); // imprima a marca de início para (int ii; t.start (); } while (true) {// Aguardando todos os threads infantis concluir a execução se (! ImportThread.hasthreadRunning ()) {break; } Thread.sleep (500); } System.out.println (Thread.currentThread (). GetName () + "end."); // Print End Tag Long tend = System.currenttimemillis (); System.out.println ("Tempo total:" + (tend - tstart) + "milhões");O resultado da impressão é:
Início principal
O thread-1 começa ...
O thread-5 começa ...
O thread-0 começa ...
O thread-2 começa ...
O thread-3 começa ...
O thread-4 começa ...
Thread-5 termina.
Thread-4 termina.
Thread-2 termina.
Thread-0 termina.
Thread-3 termina.
Thread-1 termina.
O fim de Main.
Tempo total: 20860milhões
Você pode ver que o encadeamento principal começa a executar apenas depois que todos os threads infantis são executados.
======================================================================== =========================================================================
O método acima possui um perigo oculto: se o thread 1 iniciar e terminar e outros threads ainda não começaram, o tamanho do runningthreads também é 0, o encadeamento principal pensará que todos os threads foram executados. A solução é substituir o tipo de lista runningthreads por um contador do tipo não simples, e o valor do contador deve ser definido antes da criação de encadeamentos.
MyCountdown Class
classe pública MyCountDown {private int count; public myCountDown (int conting) {this.count = count; } public sincronizado void countdown () {count--; } public sincronizado boolean hasNext () {return (contagem> 0); } public int getCount () {Return Count; } public void setCount (int conting) {this.count = count; }} Classe Importthread
classe pública ImportThread estende thread {private mycountDown c; public ImportThread (MyCountDown c) {this.c = c; } @Override public void run () {System.out.println (thread.currentThread (). GetName () + "start ..."); // imprima o marcador inicial // faça algo c.countDown (); // timer menos 1 system.out.println (thread.currentThread (); final de marca}} No tópico principal
System.out.println (thread.currentThread (). GetName ()+"start"); // imprima a etiqueta inicial MyCountDown c = new MyCountDown (Threadnum); // Inicialize a contagem regressiva para (int ii = 0; t.start (); } while (true) {// aguardando todos os threads infantis executar se (! c.hasnext ()) quebrar; } System.out.println (thread.currentThread (). GetName () + "end."); // imprima a marca finalResultado de impressão:
Início principal
O thread-2 começa ...
O thread-1 começa ...
O thread-0 começa ...
O thread-3 começa ...
O thread-5 começa ...
O thread-4 começa ...
Thread-5 termina. 5 mais tópicos
Thread-1 termina. Existem mais 4 tópicos
Thread-4 termina. Existem mais 3 tópicos
Thread-2 termina. Mais 2 threads
Thread-3 termina. 1 tópico ainda está lá
Thread-0 termina. Restam 0 tópicos
O fim de Main.
Caminho mais fácil: use java.util.concurrent.countdownlatch em vez de myCountDown, use o método Await () em vez de While (true) {...}
Classe Importthread
classe pública ImportThread estende o thread {private CountDownLatch Threadssignal; public ImportThread (CountdownLatch ThreadSSignal) {this.ThreadSSignal = Threadssignal; } @Override public void run () {System.out.println (thread.currentThread (). GetName () + "start ..."); // faça algo Threadssignal.CountDown (); // O contador é reduzido por 1 no final do sistema de thread.out.println (thread.currentThread (). GetName () + "end. Também existem" + threadssignal.getCount () + "Threads"); }} No tópico principal
CountDownLatch ThreadSignal = new Countdownlatch (Threadnum); // Inicialize a contagem regressiva para (int ii = 0; ii <Threadnum; ii ++) {// Abra threads ITERATOR FINAL <String> itt = it.get (ii); Thread t = new importThread (itt, sql, threadsignal); t.start (); } threadsignal.await (); // aguardando todos os threads infantis concluir o sistema de execução.out.println (thread.currentThread (). getName () + "end"); // imprima a marca final da marcaResultado de impressão:
Início principal
O thread-1 começa ...
O thread-0 começa ...
O thread-2 começa ...
O thread-3 começa ...
O thread-4 começa ...
O thread-5 começa ...
Thread-0 termina. 5 mais tópicos
Thread-1 termina. Existem mais 4 tópicos
Thread-4 termina. Existem mais 3 tópicos
Thread-2 termina. Mais 2 threads
Thread-5 termina. 1 tópico ainda está lá
Thread-3 termina. Restam 0 tópicos
O fim de Main.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.