내 친구는 텍스트 문서에서 데이터를 Oracle 데이터베이스로 가져 오는 프로그램을 작성하도록 도와달라고 요청했습니다. 기술적으로 어렵지 않습니다. 문서의 형식이 수정되었습니다. 데이터베이스의 해당 필드 분석이 충분한 한, 핵심은 성능에 있습니다.
데이터 볼륨은 많고 수백만 개의 레코드입니다. 따라서 멀티 스레드 동시 실행을 사용해야하고 작문 과정에서 문제가 발생한다는 점을 고려하면 실행이 완료된 후 모든 아동 프로세스에 소요 된 총 시간을 계산하고 싶습니다. 첫 번째 자식 과정이 생성되기 전에 현재 시간을 기록하십시오. System.CurrentTimeMillis ()를 사용하여 마지막 아동 프로세스가 완료된 후 현재 시간을 기록하십시오. 뺄셈에 의해 얻은 시차는 총 시간입니다. 코드는 다음과 같습니다
long tstart = system.currenttimeMillis (); system.out.println (thread.currentthread (). getName () + "start"); // 시작 마크 (int ii = 0; ii <threadnum; ii ++) {// runnable r = new Runnable () {@override public void run () {system.out.printthread ()); // 무언가를 ... ... System.out.println (thread.currentThread (). getName () + "end."); }} 스레드 t = 새 스레드 (r); t.start (); } system.out.println (Thread.currentThread (). getName () + "end."); // 인쇄 끝 tag long tend = system.currentTimeMillis (); System.out.println ( "총 시간 :" + (tend -tstart) + "millions"); 결과적으로 주 스레드가 총 시간을 인쇄하는 데 사용한 진술은 루프가 끝나는 순간 거의 실행됩니다. 그 이유는 모든 어린이 스레드가 동시에 실행되고 주 스레드가 실행될 때도 실행되기 때문입니다. "메인 스레드가 모든 어린이 스레드가 실행되기를 기다리는 방법"이라는 질문이 제기됩니다. 각 어린이 스레드가 시작된 후 T.join ()을 추가하려고 시도했으며 결과는 모든 스레드가 순차적으로 실행되므로 동시성의 의미를 상실합니다.
Google은 온라인에서 오랫동안 솔루션을 찾지 못했습니다. 아무도 그런 필요성을 얻지 못했습니까? 아니면이 문제가 너무 간단합니까? 우 나이는 해결책을 스스로 생각해야했다 ...
마지막으로, 내 솔루션은 java.lang.thread에서 importthread 클래스 상속을 사용자 정의하고 run () 메소드를 과부하하고 목록 속성을 사용하여 생성 된 모든 스레드를 저장하는 것입니다. 이런 식으로, 목록이 비어 있는지 판단하는 한, 실행되지 않은 자식 실이 여전히 있는지 알 수 있습니다. 클래스 코드는 다음과 같습니다.
public class importthread는 스레드를 확장합니다 {private static list <theld> runnidethreads = new ArrayList <Stride> (); public importthread () {} @override public void run () {registration (this); // register system.out.println (thread.currentThread (). getName () + "시작 ..."); // 시작 마커를 인쇄 ... "end."); // end tag 인쇄} public void registration (스레드 t) {synchronized (runningthreads) {runningthreads.add (t); }} public void unregist (스레드 t) {synchronized (runningthreads) {synchronized (runningthreads) {runningthreads.remove (t); }} public static boolean hasthreadRunning () {return (runningthreads.size ()> 0); // runningthreads가 비어 있는지 판단하여 여전히 실행되지 않은 스레드가 있는지 여부를 알 수 있습니다}} 메인 스레드의 코드 :
long tstart = system.currenttimeMillis (); system.out.println (thread.currentThread (). getName ()+"start"); // (int ii = 0; ii <ThreadNum; ii ++) {// 스레드 t = new importThread (); t.start (); } while (true) {// 모든 자식 스레드가 실행을 완료하기를 기다리고 있습니다. } thread.sleep (500); } system.out.println (Thread.currentThread (). getName () + "end."); // 인쇄 끝 tag long tend = system.currentTimeMillis (); System.out.println ( "총 시간 :" + (tend -tstart) + "millions");인쇄 결과는 다음과 같습니다.
메인 시작
스레드 1 시작 ...
스레드 -5 시작 ...
스레드 -0은 시작 ...
스레드 -2 시작 ...
스레드 -3 시작 ...
스레드 -4 시작 ...
스레드 -5가 끝납니다.
스레드 -4가 끝납니다.
스레드 -2가 끝납니다.
스레드 -0이 끝납니다.
스레드 -3가 끝납니다.
스레드 -1이 끝납니다.
메인의 끝.
총 시간 : 20860millions
메인 스레드는 모든 자식 스레드가 실행 된 후에 만 실행을 시작한다는 것을 알 수 있습니다.
=============================================================================== =================================================================================
위의 방법은 숨겨진 위험이 있습니다. 스레드 1이 시작되고 끝나고 다른 스레드가 아직 시작되지 않은 경우 RunningThreads의 크기도 0이면 기본 스레드는 모든 스레드가 실행되었다고 생각합니다. 솔루션은 목록 유형 RunningThreads를 비소 유형 카운터로 바꾸는 것이며 스레드 생성 전에 카운터 값을 설정해야합니다.
MyCountdown 클래스
공개 클래스 MyCountdown {private int count; public mycountdown (int count) {this.count = count; } public synchronized void countdown () {count-; } public synchronized boolean hasnext () {return (count> 0); } public int getCount () {return count; } public void setCount (int count) {this.count = count; }} importthread 클래스
Public Class importthread는 스레드 {private mycountdown c; public importthread (mycountdown c) {this.c = c; } @override public void run () {system.out.println (ride.currentthread (). getName () + "시작 ..."); // start 마커를 인쇄 // 무언가를 인쇄 c.countdown (); // timer minus 1 system.out.println (stread.currentthread (). 엔드 마크}} 메인 스레드에서
System.out.println (thread.currentThread (). getName ()+"start"); // 시작 태그 인쇄 myCountDown c = new myCountdown (ridslenum); // countdown (int ii = 0; ii <스레드 나무름; ii ++) {// strelds t = new importthread (c); t.start (); } while (true) {// 모든 자식 스레드가 if (! c.hasnext ()) break를 실행하기를 기다리고 있습니다. } system.out.println (Thread.currentThread (). getName () + "end."); // 끝 마크를 인쇄합니다인쇄 결과 :
메인 시작
스레드 -2 시작 ...
스레드 1 시작 ...
스레드 -0은 시작 ...
스레드 -3 시작 ...
스레드 -5 시작 ...
스레드 -4 시작 ...
스레드 -5가 끝납니다. 5 더 많은 스레드
스레드 -1이 끝납니다. 스레드가 4 개 더 있습니다
스레드 -4가 끝납니다. 스레드가 3 개 더 있습니다
스레드 -2가 끝납니다. 2 스레드 더
스레드 -3가 끝납니다. 1 개의 스레드가 여전히 있습니다
스레드 -0이 끝납니다. 스레드가 0 개 남아 있습니다
메인의 끝.
쉬운 방법 : java.util.concurrent.countdownlatch를 사용하여 myCountdown 대신 await () 메소드를 사용하십시오 (true) {...}
importthread 클래스
Public Class importthread는 스레드 {private countdownlatch streadssignal; public importthread (countdownlatch streadsSignal) {this.threadsSignal = ThreadsSignal; } @override public void run () {system.out.println (thread.currentthread (). getName () + "시작 ..."); // 스레드 signal.countdown (); // 스레드 시스템의 끝에서 카운터가 1 씩 줄어 듭니다. }} 메인 스레드에서
COUNTDOWNLATCH THREADSIGNAL = NEW COUNTDOWNLATCH (THREADNUM); // (int II = 0; ii <ThreadNum; II ++)에 대한 카운트 다운 초기화 {// 열린 스레드 최종 반복자 <string> itt = it.get (ii); 스레드 t = new importthread (ITT, SQL, ThreadSignal); t.start (); } threadSignal.await (); // 모든 자식 스레드가 Execution System.out.println을 완료하기 위해 기다리고인쇄 결과 :
메인 시작
스레드 1 시작 ...
스레드 -0은 시작 ...
스레드 -2 시작 ...
스레드 -3 시작 ...
스레드 -4 시작 ...
스레드 -5 시작 ...
스레드 -0이 끝납니다. 5 더 많은 스레드
스레드 -1이 끝납니다. 스레드가 4 개 더 있습니다
스레드 -4가 끝납니다. 스레드가 3 개 더 있습니다
스레드 -2가 끝납니다. 2 스레드 더
스레드 -5가 끝납니다. 1 개의 스레드가 여전히 있습니다
스레드 -3가 끝납니다. 스레드가 0 개 남아 있습니다
메인의 끝.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.