Java concurrency 의 Condition 조건동력 노드 자바 대학 정리
Condition 의 역할 은 자 물 쇠 를 더욱 정확하게 제어 하 는 것 이다.Condition 의 await () 방법 은 Object 의 wait () 방법, Condition 의 signal () 방법 은 Object 의 notify () 방법, Condition 의 signal All () 은 Object 의 notify All () 방법 에 해당 합 니 다.다른 것 은 Object 의 wait (), notify (), notify All () 방법 은 '동기 화 잠 금' (synchronized 키워드) 과 묶 어서 사용 합 니 다.반면 Condition 은 '상호 배척 자물쇠'/'공유 자물쇠' 와 묶 어 사용 해 야 한다.
Condition 함수 목록
// 。
void await()
// 、 。
boolean await(long time, TimeUnit unit)
// 、 。
long awaitNanos(long nanosTimeout)
// 。
void awaitUninterruptibly()
// 、 。
boolean awaitUntil(Date deadline)
// 。
void signal()
// 。
void signalAll()
Condition 예제
예제 1 은 Object 의 wait (), notify () 를 통 해 스 레 드 의 휴면/깨 우기 기능 을 보 여 줍 니 다.
예제 2 는 Condition 의 await (), signal () 을 통 해 스 레 드 의 휴면/깨 우기 기능 을 보 여 줍 니 다.
예시 3 은 Condition 을 통과 하 는 고급 기능 이다.
예시 1
public class WaitTest1 {
public static void main(String[] args) {
ThreadA ta = new ThreadA("ta");
synchronized(ta) { // synchronized(ta) “ ta ”
try {
System.out.println(Thread.currentThread().getName()+" start ta");
ta.start();
System.out.println(Thread.currentThread().getName()+" block");
ta.wait(); //
System.out.println(Thread.currentThread().getName()+" continue");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadA extends Thread{
public ThreadA(String name) {
super(name);
}
public void run() {
synchronized (this) { // synchronized(this) “ ”
System.out.println(Thread.currentThread().getName()+" wakup others");
notify(); // “ ”
}
}
}
}
예시 2
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest1 {
private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public static void main(String[] args) {
ThreadA ta = new ThreadA("ta");
lock.lock(); //
try {
System.out.println(Thread.currentThread().getName()+" start ta");
ta.start();
System.out.println(Thread.currentThread().getName()+" block");
condition.await(); //
System.out.println(Thread.currentThread().getName()+" continue");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //
}
}
static class ThreadA extends Thread{
public ThreadA(String name) {
super(name);
}
public void run() {
lock.lock(); //
try {
System.out.println(Thread.currentThread().getName()+" wakup others");
condition.signal(); // “condition ”
} finally {
lock.unlock(); //
}
}
}
}
실행 결과:
main start ta
main block
ta wakup others
main continue
"예제 1"과 "예제 2"를 통 해 Condition 과 Object 의 방법 이 대응 하 는 관 계 를 가 진 다 는 것 을 알 수 있 습 니 다.
Object Condition 휴면 wait await 스 레 드 깨 우기 notify signal 모든 스 레 드 깨 우기 notifyAll signalAll
Condition 은 위의 기능 을 지원 하 는 것 외 에 더 강 한 점 은 다 중 스 레 드 의 휴면 과 각성 을 더욱 정교 하 게 제어 할 수 있다 는 것 이다.같은 자물쇠 에 대해 서 는 여러 개의 Condition 을 만 들 고 서로 다른 상황 에서 서로 다른 Condition 을 사용 할 수 있 습 니 다.
예 를 들 어 다 중 스 레 드 가 같은 버퍼 를 읽 거나 쓰 면 버퍼 에 데 이 터 를 기록 한 후에 '읽 기 스 레 드' 를 깨 웁 니 다.버퍼 에서 데 이 터 를 읽 은 후에 '쓰기 스 레 드' 를 깨 웁 니 다.또한 버퍼 가 가득 찼 을 때 '스 레 드 쓰기' 는 기 다 려 야 합 니 다.버퍼 가 비어 있 을 때 '읽 기 스 레 드' 는 기 다 려 야 합 니 다. Object 클래스 의 wait (), notify (), notify All () 을 사용 하면 버퍼 에 데 이 터 를 기록 한 후 '읽 기 스 레 드' 를 깨 워 야 할 때 notify () 나 notify All () 을 통 해 '읽 기 스 레 드' 를 명확 하 게 지정 할 수 없고 notify All 을 통 해 모든 스 레 드 를 깨 울 수 있 습 니 다 (단, notify All 은 깨 운 스 레 드 가 읽 기 스 레 드 인지 쓰기 스 레 드 인지 구분 할 수 없습니다). 단, Condition 을 통 해 읽 기 스 레 드 를 명확 하 게 지정 할 수 있 습 니 다.
아래 의 예 3 을 보면 이 개념 에 대해 더욱 깊이 이해 할 수 있 을 것 이다.
예시 3
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[5];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock(); //
try {
// “ ”, ; “ ” , x 。
while (count == items.length)
notFull.await();
// x
items[putptr] = x;
// “put putptr+1”; “ ”, putptr 0。
if (++putptr == items.length) putptr = 0;
// “ ” +1
++count;
// take , take notEmpty.await()
notEmpty.signal();
//
System.out.println(Thread.currentThread().getName() + " put "+ (Integer)x);
} finally {
lock.unlock(); //
}
}
public Object take() throws InterruptedException {
lock.lock(); //
try {
// “ ”, ; “ ” , x 。
while (count == 0)
notEmpty.await();
// x
Object x = items[takeptr];
// “take takeptr+1”; “ ”, takeptr 0。
if (++takeptr == items.length) takeptr = 0;
// “ ” -1
--count;
// put , put notFull.await()
notFull.signal();
//
System.out.println(Thread.currentThread().getName() + " take "+ (Integer)x);
return x;
} finally {
lock.unlock(); //
}
}
}
public class ConditionTest2 {
private static BoundedBuffer bb = new BoundedBuffer();
public static void main(String[] args) {
// 10 “ ”, BoundedBuffer ( 0-9);
// 10 “ ”, BoundedBuffer 。
for (int i=0; i<10; i++) {
new PutThread("p"+i, i).start();
new TakeThread("t"+i).start();
}
}
static class PutThread extends Thread {
private int num;
public PutThread(String name, int num) {
super(name);
this.num = num;
}
public void run() {
try {
Thread.sleep(1); // 1ms
bb.put(num); // BoundedBuffer
} catch (InterruptedException e) {
}
}
}
static class TakeThread extends Thread {
public TakeThread(String name) {
super(name);
}
public void run() {
try {
Thread.sleep(10); // 1ms
Integer num = (Integer)bb.take(); // BoundedBuffer
} catch (InterruptedException e) {
}
}
}
}
(한 번) 실행 결과:
p1 put 1 p4 put 4 p5 put 5 p0 put 0 p2 put 2 t0 take 1 p3 put 3 t1 take 4 p6 put 6 t2 take 5 p7 put 7 t3 take 0 p8 put 8 t4 take 2 p9 put 9 t5 take 3 t6 take 6 t7 take 7 t8 take 8 t9 take 9
결과 설명:
(01) Bounded Buffer 는 용량 이 5 인 버퍼 이 고 버퍼 에 Object 대상 이 저장 되 어 있 으 며 다 중 스 레 드 의 읽 기/쓰기 버퍼 를 지원 합 니 다.여러 스 레 드 가 '하나의 Bounded Buffer 대상' 을 조작 할 때 서로 배척 하 는 lock 을 통 해 버퍼 항목 에 대해 서로 배척 하 는 접근 을 합 니 다.또한 같은 Bounded Buffer 대상 의 모든 스 레 드 는 'notFull' 과 'notEmpty' 라 는 두 Condition 을 공유 합 니 다.
notFull 은 쓰기 버퍼 를 제어 하 는 데 사 용 됩 니 다. notEmpty 는 읽 기 버퍼 를 제어 하 는 데 사 용 됩 니 다.버퍼 가 가득 찼 을 때 put 를 호출 하 는 스 레 드 는 notFull. await () 를 실행 하여 기 다 립 니 다.버퍼 가 가득 찬 상태 가 아 닐 때 대상 을 버퍼 에 추가 하고 버퍼 의 용량 count + 1 을 마지막 으로 notEmpty. signal () 버퍼 notEmpty 의 대기 스 레 드 (notEmpty. await 스 레 드 호출) 를 호출 합 니 다.즉, notFull 는 '버퍼 의 기록' 을 제어 합 니 다. 버퍼 에 데 이 터 를 기록 하면 notEmpty 의 대기 스 레 드 를 깨 웁 니 다.
마찬가지 로 notEmpty 는 '버퍼 읽 기' 를 제어 합 니 다. 버퍼 데 이 터 를 읽 은 후에 notFull 의 대기 스 레 드 를 깨 웁 니 다.
(02) Condition Test 2 의 main 함수 에서 10 개의 "쓰기 스 레 드"를 시작 하여 Bounded Buffer 에 끊임없이 데 이 터 를 쓰기 (0 - 9 쓰기);동시에 10 개의 '읽 기 스 레 드' 를 시작 하여 Bounded Buffer 에서 데 이 터 를 계속 읽 습 니 다.
(03) 운행 결 과 를 간단하게 분석한다.
1, p1 스 레 드 는 버퍼 에 1 을 기록 합 니 다. 이 때 버퍼 데이터: | 1 | | | | |
2, p4 스 레 드 는 버퍼 에 4 를 기록 합 니 다. 이 때 버퍼 데이터: | 1 | 4 | | | |
3, p5 스 레 드 버퍼 에 5 를 기록 합 니 다. 이 때 버퍼 데이터: | 1 | 4 | 5 | | |
4, p0 스 레 드 는 버퍼 에 0 을 기록 합 니 다. 이 때 버퍼 데이터: | 1 | 4 | 5 | 0 | |
5, p2 스 레 드 버퍼 에 2 를 기록 합 니 다. 이 때 버퍼 데이터: | 1 | 4 | 5 | 0 | 2 |
이때 버퍼 용량 은 5 입 니 다.버퍼 가 가득 찼 습 니 다!이 때 버퍼 에 데 이 터 를 쓰 려 면 put 에 있 는 notFull. await () 를 호출 하여 대기 하고 버퍼 가 가득 차지 않 은 상태 에서 만 계속 실행 할 수 있 습 니 다.
6. t0 스 레 드 는 버퍼 에서 데이터 1 을 꺼 냅 니 다.이 때 버퍼 데이터: | | 4 | 5 | 0 | 2 |
7, p3 스 레 드 는 버퍼 에 3 을 기록 합 니 다. 이 때 버퍼 데이터: | 3 | 4 | 5 | 0 | 2 |
8. t1 스 레 드 는 버퍼 에서 데 이 터 를 꺼 냅 니 다.이 때 버퍼 데이터: | 3 | | 5 | 0 | 2 |
9, p6 스 레 드 는 버퍼 에 6 을 기록 합 니 다. 이 때 버퍼 데이터: | 3 | 6 | 5 | 0 | 2 | ...
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.