자바 비동기 호출 동기 화 방법 인 스 턴 스 상세 설명
동기 호출:호출 자가 호출 과정 에서 결 과 를 되 돌려 주 기 를 계속 기다 리 고 있 습 니 다.
비동기 호출:호출 자 는 호출 과정 에서 결 과 를 직접 기다 리 지 않 고 다른 작업 을 수행 합 니 다.결과 반환 형식 은 보통 리 셋 함수 입 니 다.
사실 이들 의 차 이 는 매우 뚜렷 하 다.여기 서도 자세히 말 하지 않 겠 다.우 리 는 자바 가 어떻게 비동기 호출 을 동기 화 하 는 지 에 대해 이야기 하 자.다시 말 하면 비동기 가 필요 하 다 는 것 이다.
호출 과정 에서 호출 결 과 를 얻 을 때 까지 계속 차단 합 니 다.
뜸 을 들 이지 않 고 먼저 다섯 가지 방법 을 열거 한 다음 에 일일이 예 를 들 어 설명 한다.
우선,demo 를 쓰 려 면 인 프 라 를 먼저 써 야 한다.여기 서 는 주로 비동기 호출 모델 을 구축 해 야 한다.비동기 호출 클래스:
public class AsyncCall {
private Random random = new Random(System.currentTimeMillis());
private ExecutorService tp = Executors.newSingleThreadExecutor();
//demo1,2,4,5
public void call(BaseDemo demo){
new Thread(()->{
long res = random.nextInt(10);
try {
Thread.sleep(res*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
demo.callback(res);
}).start();
}
//demo3
public Future<Long> futureCall(){
return tp.submit(()-> {
long res = random.nextInt(10);
try {
Thread.sleep(res*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return res;
});
}
public void shutdown(){
tp.shutdown();
}
}
우 리 는 주로 call 방법 에 관심 을 가지 고 있 습 니 다.이 방법 은 demo 인 자 를 받 았 고 스 레 드 를 열 어 스 레 드 에서 구체 적 인 임 무 를 수행 하고 demo 의 callback 방법 으로 리 셋 함수 호출 을 했 습 니 다.여러분 은 이곳 의 반환 결 과 는[0,10)의 긴 정형 이 고 결과 가 얼마 인지 알 게 되 었 습 니 다.이 는 주로 실험 결 과 를 잘 관찰 하고 비동기 호출 과정 에서 의 처리 시간 을 모 의 하기 위 한 것 입 니 다.future Call 과 shutdown 방법,그리고 스 레 드 탱크 tp 는 모두 demo 3 를 이용 하여 Future 를 이용 하여 준비 한 것 입 니 다.
demo 의 기본 클래스:
public abstract class BaseDemo {
protected AsyncCall asyncCall = new AsyncCall();
public abstract void callback(long response);
public void call(){
System.out.println(" ");
asyncCall.call(this);
System.out.println(" ");
}
}
BaseDemo 는 매우 간단 합 니 다.그 안에 비동기 호출 클래스 의 인 스 턴 스 가 포함 되 어 있 습 니 다.다른 콜 방법 은 비동기 호출 을 시작 하 는 데 사 용 됩 니 다.물론 하나의 추상 적 인 방법 인 callback 은 모든 demo 가 실현 해 야 합 니 다.-주로 반전 에서 해당 하 는 처 리 를 하여 비동기 호출 동기 화 목적 을 달성 해 야 합 니 다.1.wait 와 notify 방법 사용
이 방법 은 사실 자물쇠 메커니즘 을 이용 하여 코드 를 직접 붙 이 는 것 이다.
public class Demo1 extends BaseDemo{
private final Object lock = new Object();
@Override
public void callback(long response) {
System.out.println(" ");
System.out.println(response);
System.out.println(" ");
synchronized (lock) {
lock.notifyAll();
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
demo1.call();
synchronized (demo1.lock){
try {
demo1.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(" ");
}
}
호출 을 시작 한 후 메 인 스 레 드 는 wait 를 이용 하여 차단 하고 리 셋 을 기다 리 는 중 notify 나 notify All 방법 으로 깨 우 는 것 을 볼 수 있 습 니 다.여러분 이 인식 하 는 것 과 마찬가지 로 여기 wait 와 notify 는 대상 의 자 물 쇠 를 먼저 받 아야 합 니 다.메 인 스 레 드 에서 마지막 으로 우 리 는 하나의 내용 을 인쇄 했 습 니 다.이것 도 실험 결 과 를 검증 하 는 데 사 용 됩 니 다.wait 와 notify 가 없 으 면 메 인 스 레 드 내용 은 호출 내용 에 따라 즉시 인쇄 됩 니 다.위의 코드 와 같이 메 인 스 레 드 내용 은 리 셋 함수 호출 이 끝 날 때 까지 기 다 려 야 인쇄 할 수 있 습 니 다.동기 화 작업 을 사용 하지 않 은 상태 에서 결 과 를 인쇄 합 니 다.
호출 을 개시 하 다
호출 되 돌아 오기
메 인 스 레 드 내용
결 과 를 얻다
1
호출 끝
동기 화 작업 을 사용 한 후:
호출 을 개시 하 다
호출 되 돌아 오기
결 과 를 얻다
9
호출 끝
메 인 스 레 드 내용
2.사용 조건 잠 금
방법 1 의 원리 와 유사 하 다.
public class Demo2 extends BaseDemo {
private final Lock lock = new ReentrantLock();
private final Condition con = lock.newCondition();
@Override
public void callback(long response) {
System.out.println(" ");
System.out.println(response);
System.out.println(" ");
lock.lock();
try {
con.signal();
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
demo2.call();
demo2.lock.lock();
try {
demo2.con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
demo2.lock.unlock();
}
System.out.println(" ");
}
}
기본적으로 방법 과 별 차이 가 없다.다만 여기 서 조건 자 물 쇠 를 사 용 했 을 뿐 이들 의 자물쇠 체 제 는 다소 다르다.3. Future
Future 를 사용 하 는 방법 은 이전 과 달리 우리 가 사용 하 는 비동기 방법 도 다르다.
public class Demo3{
private AsyncCall asyncCall = new AsyncCall();
public Future<Long> call(){
Future<Long> future = asyncCall.futureCall();
asyncCall.shutdown();
return future;
}
public static void main(String[] args) {
Demo3 demo3 = new Demo3();
System.out.println(" ");
Future<Long> future = demo3.call();
System.out.println(" ");
while (!future.isDone() && !future.isCancelled());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println(" ");
}
}
future Call 방법 을 호출 합 니 다.방법 에 서 는 스 레 드 탱크 tp 가 Callable 을 제출 하고 Future 로 돌아 가 려 고 합 니 다.이 Future 는 우리 demo 3 에서 call 에서 얻 은 것 입 니 다.future 대상 을 얻 으 면 스 레 드 탱크 를 닫 을 수 있 습 니 다.asyncCall 의 shutdown 방법 을 호출 할 수 있 습 니 다.스 레 드 풀 을 닫 는 데 주의 할 점 이 있 습 니 다.asyncCall 의 shutdown 방법 을 돌아 보 겠 습 니 다.
public void shutdown(){
tp.shutdown();
}
스 레 드 탱크 의 shutdown 방법 만 간단하게 호출 한 것 을 발견 하고 주의 점 을 말 합 니 다.여 기 는 tp 의 shutdown Now 방법 을 사용 하지 않 는 것 이 좋 습 니 다.이 방법 은 스 레 드 에서 실행 중인 작업 을 중단 하려 고 합 니 다.이 방법 을 사용 하면 우리 퓨 처 에 대응 하 는 임무 가 중 단 돼 수행 결 과 를 얻 지 못 할 수도 있다 는 것 이다.그 다음 에 우 리 는 메 인 스 레 드 의 내용 에 관심 을 가지 고 메 인 스 레 드 의 차단 은 우리 스스로 이 루어 집 니 다.future 의 isDone 과 isCanceled 를 통 해 실행 상 태 를 판단 하고 실행 이 완료 되 거나 취 소 될 때 까지 합 니 다.그 후에 우 리 는 get 의 결 과 를 인쇄 합 니 다.
4.CountDownlatch 사용
Countdown Latch 를 사용 하 는 것 은 아마도 일상 프로 그래 밍 에서 가장 흔히 볼 수 있 는 것 일 것 입 니 다.또한 상대 적 으로 우아 한 것 같 습 니 다.
public class Demo4 extends BaseDemo{
private final CountDownLatch countDownLatch = new CountDownLatch(1);
@Override
public void callback(long response) {
System.out.println(" ");
System.out.println(response);
System.out.println(" ");
countDownLatch.countDown();
}
public static void main(String[] args) {
Demo4 demo4 = new Demo4();
demo4.call();
try {
demo4.countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" ");
}
}
평소 사용 하 시 는 것 처럼,이 곳 은 메 인 스 레 드 에서 CountDownlatch 의 await 방법 을 이용 하여 차단 합 니 다.리 셋 에서 countDown 방법 을 이용 하여 다른 스 레 드 await 부분 을 계속 실행 할 수 있 습 니 다.물론,여 기 는 demo 1 과 demo 2 와 마찬가지 로 메 인 스 레 드 에서 막 힌 부분 은 시간 초과 시간 을 설정 할 수 있 습 니 다.시간 초과 후 더 이상 막 히 지 않 을 수 있 습 니 다.
5.CyclicBarrier 사용
public class Demo5 extends BaseDemo{
private CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
@Override
public void callback(long response) {
System.out.println(" ");
System.out.println(response);
System.out.println(" ");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo5 demo5 = new Demo5();
demo5.call();
try {
demo5.cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(" ");
}
}
여러분,Cyclic Barrier 와 Count Downlatch 는 단지 유사 할 뿐,둘 은 어느 정도 차이 가 있 습 니 다.예 를 들 어 하 나 는 덧셈 으로 이해 할 수 있 고 이 숫자 에 추 가 된 후에 함께 운행 할 수 있다.하 나 는 감법 으로 0 으로 줄 여 계속 운행 한다.하 나 는 반복 해서 계산 할 수 있다.하 나 는 안 돼.잠깐 만.잠깐 만.또 Cyclic Barrier 를 사용 할 때 는 두 가 지 를 주의해 야 한다.첫 번 째,초기 화 할 때 매개 변수 숫자 는 2 로 설정 해 야 합 니 다.비동기 호출 은 하나의 스 레 드 이 고 메 인 스 레 드 는 하나의 스 레 드 입 니 다.두 스 레 드 가 모두 await 일 때 만 계속 실 행 됩 니 다.이것 도 Countdown Latch 와 구별 되 는 부분 입 니 다.두 번 째 는 매개 변 수 를 초기 화 하 는 수치 에 관 한 것 입 니 다.여기 demo 와 상 관 없 이 평소에 프로 그래 밍 할 때 조심해 야 합 니 다.만약 에 이 수치 가 크게 설정 되 어 스 레 드 탱크 의 스 레 드 수 보다 크 면 잠 금 을 일 으 키 기 쉽 습 니 다.
총결산
종합 하면 이번에 말 해 야 할 몇 가지 방법 이다.사실 모든 방법 은 같은 원리 이다.즉,호출 된 스 레 드 에서 결 과 를 막 고 리 셋 에서 함수 에서 차단 상 태 를 해제 하 는 것 이다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.