Java 스레드가 다른 스레드의 출력을 대기하도록 하려면 어떻게 해야 합니까?
애플리케이션 논리 스레드와 데이터베이스 액세스 스레드를 사용하여 Java 애플리케이션을 만들고 있습니다.둘 다 애플리케이션의 라이프 타임 전체에 걸쳐 지속되며 동시에 실행되어야 합니다(서버와 대화하고 사용자와 대화하며, 앱이 완전히 시작되면 둘 다 작동해야 합니다).
그러나 시작 시 앱 스레드가 처음에 DB 스레드가 준비될 때까지 기다려야 합니다(현재 커스텀 메서드를 폴링하여 결정됨).dbthread.isReady()
db 스레드가 준비될 때까지 앱 스레드가 차단되어도 상관없습니다.
Thread.join()
db 스레드는 앱 종료 시에만 종료됩니다.
while (!dbthread.isReady()) {}
동작하지만 빈 루프는 프로세서 사이클을 많이 소비합니다.
다른 생각 있나요?감사해요.
카운터가 1인 CountDownLatch를 사용합니다.
CountDownLatch latch = new CountDownLatch(1);
이제 앱 스레드에서 do-
latch.await();
db 스레드에서 작업을 완료한 후 다음 작업을 수행합니다.
latch.countDown();
멀티스레딩이라는 마법의 세계를 시작하기 전에 Sun의 Java Concurrency와 같은 튜토리얼을 받아보는 것을 추천합니다.
또한 "Java 동시 프로그래밍" 및 "Java Concurrent Programming in Practice"에 대한 Google도 다수 있습니다.
답변을 얻으려면:
이 코드에서는, 가 대기하고 있을 필요가 있습니다.dbThread
, 다음과 같은 것이 필요합니다.
//do some work
synchronized(objectYouNeedToLockOn){
while (!dbThread.isReady()){
objectYouNeedToLockOn.wait();
}
}
//continue with work after dbThread is ready
고객님의 고객명dbThread
의 메서드에서는 다음과 같은 작업을 수행해야 합니다.
//do db work
synchronized(objectYouNeedToLockOn){
//set ready flag to true (so isReady returns true)
ready = true;
objectYouNeedToLockOn.notifyAll();
}
//end thread run method here
그objectYouNeedToLockOn
이 예에서는 각 스레드에서 동시에 조작할 필요가 있는 오브젝트를 사용하는 것이 좋습니다.또는 다른 오브젝트를 작성할 수도 있습니다.Object
(메서드 자체를 동기화하는 것은 권장하지 않습니다)
private final Object lock = new Object();
//now use lock in your synchronized blocks
이해를 돕기 위해:
위의 작업을 수행하는 다른(때로는 더 나은) 방법이 있습니다. 예를 들어,CountdownLatches
, 등. Java 5에서는 많은 니프티 동시성 클래스가 있습니다.java.util.concurrent
패키지 및 서브패키지.동시성을 알기 위해서는 온라인에서 자료를 찾거나 좋은 책을 구해야 합니다.
요건::
- 이전 스레드가 완료될 때까지 다음 스레드의 실행을 기다립니다.
- 다음 스레드는 시간 소모에 관계없이 이전 스레드가 중지될 때까지 시작되지 않아야 합니다.
- 간단하고 사용하기 쉬워야 합니다.
답변::
@java.util.concurrent 참조.Future.get() 문서.
future.get() 필요한 경우 계산이 완료될 때까지 기다렸다가 결과를 가져옵니다.
작업 완료!!아래의 예를 참조해 주세요.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
public class ThreadTest {
public void print(String m) {
System.out.println(m);
}
public class One implements Callable<Integer> {
public Integer call() throws Exception {
print("One...");
Thread.sleep(6000);
print("One!!");
return 100;
}
}
public class Two implements Callable<String> {
public String call() throws Exception {
print("Two...");
Thread.sleep(1000);
print("Two!!");
return "Done";
}
}
public class Three implements Callable<Boolean> {
public Boolean call() throws Exception {
print("Three...");
Thread.sleep(2000);
print("Three!!");
return true;
}
}
/**
* @See java.util.concurrent.Future.get() doc
* <p>
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*/
@Test
public void poolRun() throws InterruptedException, ExecutionException {
int n = 3;
// Build a fixed number of thread pool
ExecutorService pool = Executors.newFixedThreadPool(n);
// Wait until One finishes it's task.
pool.submit(new One()).get();
// Wait until Two finishes it's task.
pool.submit(new Two()).get();
// Wait until Three finishes it's task.
pool.submit(new Three()).get();
pool.shutdown();
}
}
이 프로그램의 출력:
One...
One!!
Two...
Two!!
Three...
Three!!
다른 스레드보다 큰 작업이 완료되기까지6초 걸리는 것을 알 수 있습니다.Future.get()은 작업이 완료될 때까지 기다립니다.
future.get()을 사용하지 않으면 종료까지 기다리지 않고 시간 소모를 기준으로 실행됩니다.
Java 동시성 행운을 빕니다.
많은 정답을 맞췄지만 간단한 예는 없었다.이 있습니다.CountDownLatch
:
//inside your currentThread.. lets call it Thread_Main
//1
final CountDownLatch latch = new CountDownLatch(1);
//2
// launch thread#2
new Thread(new Runnable() {
@Override
public void run() {
//4
//do your logic here in thread#2
//then release the lock
//5
latch.countDown();
}
}).start();
try {
//3 this method will block the thread of latch untill its released later from thread#2
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//6
// You reach here after latch.countDown() is called from thread#2
public class ThreadEvent {
private final Object lock = new Object();
public void signal() {
synchronized (lock) {
lock.notify();
}
}
public void await() throws InterruptedException {
synchronized (lock) {
lock.wait();
}
}
}
이 클래스를 다음과 같이 사용합니다.
ThreadEvent를 만듭니다.
ThreadEvent resultsReady = new ThreadEvent();
이 방법에서는 결과를 기다리고 있습니다.
resultsReady.await();
또한 모든 결과가 생성된 후 결과를 생성하는 방법:
resultsReady.signal();
편집:
(이 투고를 편집하여 죄송합니다.이 코드는 레이스 상태가 매우 나쁘기 때문에 코멘트를 할 만한 평판이 없습니다.)
이것은 signal()이 wait() 뒤에 호출되는 것을 100% 확신하는 경우에만 사용할 수 있습니다.이것이 Java 오브젝트를 사용할 수 없는 큰 이유입니다.Windows 이벤트
코드가 다음 순서로 실행되는 경우:
Thread 1: resultsReady.signal();
Thread 2: resultsReady.await();
스레드 2는 영원히 대기합니다.이는 Object.notify()가 현재 실행 중인 스레드 중 하나만 웨이크업하기 때문입니다.나중에 대기하는 스레드는 깨지지 않는다.이것은 a) 대기 또는 b) 명시적으로 재설정될 때까지 이벤트가 시그널링되는 내가 기대하는 이벤트 작동 방식과는 매우 다릅니다.
주의: 대부분의 경우 notifyAll()을 사용해야 하지만 이는 위의 "wait forever" 문제와 관련이 없습니다.
CountDownLatch 클래스에서java.util.concurrent
패키지: 하위 수준보다 오류 발생률이 훨씬 낮은 상위 수준 동기화 메커니즘을 제공합니다.
2개의 스레드 간에 공유되는Exchanger 객체를 사용하여 이 작업을 수행할 수 있습니다.
private Exchanger<String> myDataExchanger = new Exchanger<String>();
// Wait for thread's output
String data;
try {
data = myDataExchanger.exchange("");
} catch (InterruptedException e1) {
// Handle Exceptions
}
그리고 두 번째 줄에서는:
try {
myDataExchanger.exchange(data)
} catch (InterruptedException e) {
}
다른 사람들이 말한 것처럼, 이 가벼운 코드와 복사 붙여넣기만 하지 마세요.먼저 읽으세요.
에서의 미래 인터페이스java.lang.concurrent
패키지는 다른 스레드에서 계산된 결과에 액세스할 수 있도록 설계되었습니다.
Future Task 및 Executor Service에서 이러한 작업을 수행하는 기성 방법을 살펴보십시오.
동시성 및 멀티스레딩에 관심이 있는 사람에게는 Java Concurency In Practice를 읽어보실 것을 강력히 권장합니다.Java에 집중되어 있는 것은 분명하지만, 다른 언어로 작업하는 사람에게는 충분한 양의 고기가 있습니다.
빠르고 더러운 것을 원한다면 스레드를 추가할 수 있습니다.sleep() 콜을 while 루프 내에서 실행합니다.데이터베이스 라이브러리를 변경할 수 없는 경우 다른 쉬운 해결책은 없습니다.대기 시간을 사용하여 데이터베이스를 폴링해도 성능은 저하되지 않습니다.
while (!dbthread.isReady()) {
Thread.sleep(250);
}
우아한 코드라고 할 수 있는 것은 아니지만, 일을 완수할 수 있습니다.
데이터베이스 코드를 수정할 수 있는 경우 다른 답변에서 제안한 대로 뮤텍스를 사용하는 것이 좋습니다.
이는 모든 언어에 적용됩니다.
사건/청취기 모형을 사용하려고 합니다.특정 이벤트를 대기할 수신기를 만듭니다.이벤트는 워커 스레드로 작성(또는 시그널링)됩니다.이렇게 하면 현재 보유하고 있는 솔루션과 같은 조건이 충족되는지 확인하기 위해 지속적으로 폴링을 수행하는 대신 신호가 수신될 때까지 스레드가 차단됩니다.
교착 상태가 발생하는 가장 일반적인 원인 중 하나입니다. 발생한 오류에 관계없이 다른 스레드에 신호를 보내야 합니다.예를 들어 응용 프로그램이 예외를 발생시키고 다른 응용 프로그램이 완료되었음을 알리기 위해 메서드를 호출하지 않습니다.이렇게 하면 다른 스레드가 '웨이크업'되지 않게 됩니다.
사례를 구현하기 전에 이 패러다임을 더 잘 이해하기 위해 이벤트 및 이벤트 핸들러를 사용하는 개념을 검토할 것을 권장합니다.
또는 뮤텍스를 사용하여 차단 함수 호출을 사용할 수 있습니다. 그러면 스레드가 리소스가 비워질 때까지 대기합니다.이를 위해서는 다음과 같은 적절한 스레드 동기화가 필요합니다.
Thread-A Locks lock-a
Run thread-B
Thread-B waits for lock-a
Thread-A unlocks lock-a (causing Thread-B to continue)
Thread-A waits for lock-b
Thread-B completes and unlocks lock-b
한 스레드의 차단 대기열을 읽고 다른 스레드에 쓸 수 있습니다.
부터
다른 방법을 고려해 볼 수 있습니다.
호출원
ExecutorService
invokeAll(Collection<? extends Callable<T>> tasks)
지정된 작업을 실행하여 모든 작업이 완료되면 상태 및 결과를 보유한 미래 목록을 반환합니다.
ForkJoinPool 또는 newWorkStealingPool 위치
Executors
8 ) (Java 8 릴리즈)사용 가능한 모든 프로세서를 대상 병렬 처리 수준으로 사용하여 작업 도용 스레드 풀을 만듭니다.
이 아이디어가 적용될 수 있을까요?만약 당신이 Countdown Latchs나 Semaphores를 사용한다면 완벽하지만, 만약 당신이 인터뷰를 위해 가장 쉬운 답을 찾고 있다면, 나는 이것이 적용될 수 있다고 생각합니다.
언급URL : https://stackoverflow.com/questions/289434/how-to-make-a-java-thread-wait-for-another-threads-output
'programing' 카테고리의 다른 글
더블을 문자열로 변환하는 중 (0) | 2022.10.28 |
---|---|
오류! MySQL 관리자 또는 서버 PID 파일을 찾을 수 없습니다!QNAP (0) | 2022.10.28 |
MariaDB 설치 - 미달 의존관계, mariadb-server-5.5 (0) | 2022.10.28 |
Python 플롯에 그리드를 그리려면 어떻게 해야 하나요? (0) | 2022.10.28 |
MySQL: Curdate() vs Now() (0) | 2022.10.28 |