Java 다중 스레드 - 모든 하위 스레드가 실행될 때까지 기본 스레드를 기다립니다.
데이터량이 매우 많은 백만 개의 기록을 가지고 있기 때문에 다중 루틴으로 병행하여 실행해야 한다는 것을 고려하여 쓰는 과정에서 또 문제가 발생했습니다. 저는 모든 하위 프로세스가 실행되는 데 총 소모된 시간을 통계하고 싶습니다. 첫 번째 하위 프로세스가 생성되기 전에 현재 시간을 시스템으로 기록하고 싶습니다.currentTimeMillis () 는 마지막 하위 프로세스가 끝난 후 현재 시간을 기록합니다. 두 번 한 번 감량한 시간차는 모두 사용됩니다. 코드는 다음과 같습니다.
long tStart = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + " ");//
for (int ii = 0; ii < threadNum; ii++) {// threadNum
Runnable r = new Runnable(){
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + " ");
// ... ...
System.out.println(Thread.currentThread().getName() + " .");
}
}
Thread t = new Thread(r);
t.start();
}
System.out.println(Thread.currentThread().getName() + " .");//
long tEnd = System.currentTimeMillis();
System.out.println(" :"+ (tEnd - tStart) + "millions");
결과는 거의 for순환이 끝나는 순간에 주 스레드 인쇄가 모두 사용될 때의 문장을 실행했다. 왜냐하면 모든 하위 스레드가 병렬적으로 실행되고 그들이 실행할 때 주 스레드도 실행되기 때문이다. 이것은 본고의 제목이 어떻게'모든 하위 스레드가 실행되기를 기다리게 하는가'라는 문제를 불러일으켰다.모든 하위 스레드가 시작된 후에 t.join () 를 추가해 보았는데, 결과는 모든 스레드가 순서대로 실행되었고, 이것은 병발의 의미를 잃었다. 분명히 내가 원하는 것이 아니다. 인터넷에서 Google이 오랫동안 해결 방안을 찾지 못했는데 이런 수요를 만난 사람이 없나요?아니면 이 문제가 너무 간단한가요?어쩔 수 없이 스스로 방법을 강구해야 하는데..
마지막으로 나의 해결 방법은 ImportThread 클래스를 자바에서 계승하는 것을 사용자 정의하는 것이다.lang.Thread,run()을 다시 불러오는 방법,List 속성으로 생성된 모든 라인을 저장합니다. 이 List가 비어 있는지 판단하면 하위 라인이 실행되지 않았는지 알 수 있습니다. 클래스 코드는 다음과 같습니다.
public class ImportThread extends Thread {
private static List<Thread> runningThreads = new ArrayList<Thread>();
public ImportThread() {
}
@Override
public void run() {
regist(this);//
System.out.println(Thread.currentThread().getName() + " ...");//
// ... ...
unRegist(this);//
System.out.println(Thread.currentThread().getName() + " .");//
}
public void regist(Thread t){
synchronized(runningThreads){
runningThreads.add(t);
}
}
public void unRegist(Thread t){
synchronized(runningThreads){
runningThreads.remove(t);
}
}
public static boolean hasThreadRunning() {
return (runningThreads.size() > 0);// runningThreads
}
}
주 스레드의 코드:
long tStart = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + " ");//
for (int ii = 0; ii < threadNum; ii++) {// threadNum
Thread t = new ImportThread();
t.start();
}
while(true){//
if(!ImportThread.hasThreadRunning()){
break;
}
Thread.sleep(500);
}
System.out.println(Thread.currentThread().getName() + " .");//
long tEnd = System.currentTimeMillis();
System.out.println(" :"+ (tEnd - tStart) + "millions");
인쇄 결과는 다음과 같습니다.main 시작
쓰레드. - 1부터...
쓰레드. - 5 부터...
쓰레드 - 0부터...
쓰레드. - 2 시작...
쓰레드. - 3 부터...
쓰레드 - 4 부터...
Thread-5 종료.
Thread-4 끝.
Thread-2 끝.
Thread-0 끝.
Thread-3 종료.
Thread-1 끝.
main 끝.
총 사용시: 20860millions
main 스레드는 모든 하위 스레드가 실행된 후에야 실행되는 것을 볼 수 있습니다.
=================================================================================================
위의 방법에는 위험이 하나 있다. 만약에 스레드 1이 시작되고 끝났고 다른 스레드가 시작되지 않았다면 이 때runningThreads의size도 0이고 메인 스레드는 모든 스레드가 실행되었다고 생각할 것이다.해결 방법은 목록형의runningThreads를 간단하지 않은 유형의 계수기로 대체하고, 라인이 만들어지기 전에 계수기의 값을 설정해야 한다.
MyCountDown 클래스
public class 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 extends Thread {
private MyCountDown c;
public ImportThread(MyCountDown c) {
this.c = c;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ...");//
//Do something
c.countDown();// 1
System.out.println(Thread.currentThread().getName() + " . " + c.getCount() + " ");//
}
}
주 스레드 중
System.out.println(Thread.currentThread().getName() + " ");//
MyCountDown c = new MyCountDown(threadNum);// countDown
for (int ii = 0; ii < threadNum; ii++) {// threadNum
Thread t = new ImportThread(c);
t.start();
}
while(true){//
if(!c.hasNext()) break;
}
System.out.println(Thread.currentThread().getName() + " .");//
인쇄 결과:main 시작
쓰레드. - 2 시작...
쓰레드. - 1부터...
쓰레드 - 0부터...
쓰레드. - 3 부터...
쓰레드. - 5 부터...
쓰레드 - 4 부터...
Thread-5 종료.아직 다섯 개의 노선이 있다
Thread-1 끝.아직 4 개의 노선이 있다
Thread-4 끝.아직 세 개의 노선이 있다
Thread-2 끝.아직 두 개의 노선이 있다
Thread-3 종료.아직 1개 남았어요.
Thread-0 끝.아직 0 개의 루트가 있다
main 끝.
더 간단한 방법:java를 사용합니다.util.concurrent.MyCountDown 대신 CountDownLatch, while (true) 대신 await () 방법으로 {...}
ImportThread 클래스
public class ImportThread extends Thread {
private CountDownLatch threadsSignal;
public ImportThread(CountDownLatch threadsSignal) {
this.threadsSignal = threadsSignal;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ...");
//Do somethings
threadsSignal.countDown();// 1
System.out.println(Thread.currentThread().getName() + " . " + threadsSignal.getCount() + " ");
}
}
주 스레드 중
CountDownLatch threadSignal = new CountDownLatch(threadNum);// countDown
for (int ii = 0; ii < threadNum; ii++) {// threadNum
final Iterator<String> itt = it.get(ii);
Thread t = new ImportThread(itt,sql,threadSignal);
t.start();
}
threadSignal.await();//
System.out.println(Thread.currentThread().getName() + " .");//
인쇄 결과:main 시작
쓰레드. - 1부터...
쓰레드 - 0부터...
쓰레드. - 2 시작...
쓰레드. - 3 부터...
쓰레드 - 4 부터...
쓰레드. - 5 부터...
Thread-0 끝.아직 다섯 개의 노선이 있다
Thread-1 끝.아직 4 개의 노선이 있다
Thread-4 끝.아직 세 개의 노선이 있다
Thread-2 끝.아직 두 개의 노선이 있다
Thread-5 종료.아직 1개 남았어요.
Thread-3 종료.아직 0 개의 루트가 있다
main 끝.
이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.