Java 스레드 통신 상세 정보
1. 전통적인 스레드 통신
일반적으로 Objeclt 클래스에서 제공하는 세 가지 방법:
동기화 방법은 동기화 모니터가this 대상이기 때문에 이 세 가지 방법을 직접 호출할 수 있다.
예는 다음과 같습니다.
public class SyncMethodThreadCommunication {
static class DataWrap{
int data = 0;
boolean flag = false;
public synchronized void addThreadA(){
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data++;
System.out.println(Thread.currentThread().getName() + " " + data);
flag = true;
notify();
}
public synchronized void addThreadB() {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data++;
System.out.println(Thread.currentThread().getName() + " " + data);
flag = false;
notify();
}
}
static class ThreadA extends Thread {
private DataWrap data;
public ThreadA(DataWrap dataWrap) {
this.data = dataWrap;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
data.addThreadA();
}
}
}
static class ThreadB extends Thread {
private DataWrap data;
public ThreadB(DataWrap dataWrap) {
this.data = dataWrap;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
data.addThreadB();
}
}
}
public static void main(String[] args) {
//
DataWrap dataWrap = new DataWrap();
new ThreadA(dataWrap).start();
new ThreadB(dataWrap).start();
}
}
코드 블록을 동기화할 때 모니터 대상을 사용하여 이 세 가지 방법을 호출해야 한다.예는 다음과 같습니다.
public class SyncBlockThreadComminication {
static class DataWrap{
boolean flag;
int data;
}
static class ThreadA extends Thread{
DataWrap dataWrap;
public ThreadA(DataWrap dataWrap){
this.dataWrap = dataWrap;
}
@Override
public void run() {
for(int i = 0 ; i < 10; i++) {
synchronized (dataWrap) {
if (dataWrap.flag) {
try {
dataWrap.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dataWrap.data++;
System.out.println(getName() + " " + dataWrap.data);
dataWrap.flag = true;
dataWrap.notify();
}
}
}
}
static class ThreadB extends Thread{
DataWrap dataWrap;
public ThreadB(DataWrap dataWrap){
this.dataWrap = dataWrap;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (dataWrap) {
if (!dataWrap.flag) {
try {
dataWrap.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dataWrap.data++;
System.out.println(getName() + " " + dataWrap.data);
dataWrap.flag = false;
dataWrap.notify();
}
}
}
}
public static void main(String[] args) {
//
DataWrap dataWrap = new DataWrap();
new ThreadA(dataWrap).start();
new ThreadB(dataWrap).start();
}
}
2. Condition 제어 스레드 통신 사용Lock 객체를 사용하여 동기화를 보장하는 경우 Condition 객체를 사용하여 조정이 보장됩니다.
예는 다음과 같습니다.
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.sun.media.sound.RIFFInvalidDataException;
import javafx.scene.chart.PieChart.Data;
public class SyncLockThreadCommunication {
static class DataWrap {
int data;
boolean flag;
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void addThreadA() {
lock.lock();
try {
if (flag) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data++;
System.out.println(Thread.currentThread().getName() + " " + data);
flag = true;
condition.signal();
} finally {
lock.unlock();
}
}
public void addThreadB() {
lock.lock();
try {
if (!flag) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data++;
System.out.println(Thread.currentThread().getName() + " " + data);
flag = false;
condition.signal();
} finally {
lock.unlock();
}
}
}
static class ThreadA extends Thread{
DataWrap dataWrap;
public ThreadA(DataWrap dataWrap) {
this.dataWrap = dataWrap;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
dataWrap.addThreadA();
}
}
}
static class ThreadB extends Thread{
DataWrap dataWrap;
public ThreadB(DataWrap dataWrap) {
this.dataWrap = dataWrap;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
dataWrap.addThreadB();
}
}
}
public static void main(String[] args) {
//
DataWrap dataWrap = new DataWrap();
new ThreadA(dataWrap).start();
new ThreadB(dataWrap).start();
}
}
그 중에서 Condition 대상의await(),singal(),singalAll()은 각각wait(), notify()와 notifyAll() 방법에 대응한다.3. 차단 대기열 BlockingQueue를 사용하여 스레드 통신 제어
BlockingQueue는Queue 인터페이스의 하위 인터페이스로 주로 스레드 통신에 사용되는데 이것은 하나의 특징을 가지고 있다. 생산자의 스레드가 BlockingQueue에 요소를 넣으려고 할 때 대기열이 가득 차면 이 스레드가 막힌다.소비자 스레드가 BlockingQueue에서 요소를 꺼내려고 할 때 대기열이 비어 있으면 이 스레드가 막힙니다.이 두 가지 특징은 각각 두 가지 차단 지원 방법,put(E)와 take()에 대응한다
예는 다음과 같습니다.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueThreadComminication {
static class DataWrap{
int data;
}
static class ThreadA extends Thread{
private BlockingQueue<DataWrap> blockingQueue;
public ThreadA(BlockingQueue<DataWrap> blockingQueue, String name) {
super(name);
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
DataWrap dataWrap = blockingQueue.take();
dataWrap.data++;
System.out.println(getName() + " " + dataWrap.data);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class ThreadB extends Thread{
private BlockingQueue<DataWrap> blockingQueue;
private DataWrap dataWrap;
public ThreadB(BlockingQueue<DataWrap> blockingQueue, DataWrap dataWrap, String name) {
super(name);
this.blockingQueue = blockingQueue;
this.dataWrap = dataWrap;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
dataWrap.data++;
System.out.println(getName() + " " + dataWrap.data);
blockingQueue.put(dataWrap);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
///
DataWrap dataWrap = new DataWrap();
BlockingQueue<DataWrap> blockingQueue = new ArrayBlockingQueue<>(1);
new ThreadA(blockingQueue, "Consumer").start();
new ThreadB(blockingQueue, dataWrap, "Producer").start();
}
}
BlockingQueue에는 다음과 같은 5가지 구현 클래스가 있습니다.ArrayBlockingQueue 배열 기반 BlockingQueue 대기열
LinkedBlockingQueue 체인 테이블 기반 BlockingQueue 대기열
Priority BlockingQueue에서 요소는 Comparable 인터페이스를 실현해야 합니다. 그 중에서 요소의 정렬은 Comparator에 따라 맞춤형 정렬됩니다.
SynchronousQueue 동기화 대기열은 이 대기열에 대한 접근을 교체해야 합니다.
DelayQueue 집합 요소는 Delay 인터페이스를 구현해야 합니다. 대기열의 요소 정렬은 Delay 인터페이스 방법인 getDelay () 의 반환값에 따라 정렬됩니다.
이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.