자바 비동기 호출 동기 화 방법 인 스 턴 스 상세 설명

먼저 비동기 와 동기 화 에 대한 이 해 를 말씀 드 리 겠 습 니 다.
동기 호출:호출 자가 호출 과정 에서 결 과 를 되 돌려 주 기 를 계속 기다 리 고 있 습 니 다.
비동기 호출:호출 자 는 호출 과정 에서 결 과 를 직접 기다 리 지 않 고 다른 작업 을 수행 합 니 다.결과 반환 형식 은 보통 리 셋 함수 입 니 다.
사실 이들 의 차 이 는 매우 뚜렷 하 다.여기 서도 자세히 말 하지 않 겠 다.우 리 는 자바 가 어떻게 비동기 호출 을 동기 화 하 는 지 에 대해 이야기 하 자.다시 말 하면 비동기 가 필요 하 다 는 것 이다.
호출 과정 에서 호출 결 과 를 얻 을 때 까지 계속 차단 합 니 다.
뜸 을 들 이지 않 고 먼저 다섯 가지 방법 을 열거 한 다음 에 일일이 예 를 들 어 설명 한다.
  • wait 와 notify 방법 사용
  • 사용 조건 잠 금
  • Future
  • CountDownlatch 사용
  • CyclicBarrier 사용
  • 0.비동기 호출 구성
    우선,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 와 상 관 없 이 평소에 프로 그래 밍 할 때 조심해 야 합 니 다.만약 에 이 수치 가 크게 설정 되 어 스 레 드 탱크 의 스 레 드 수 보다 크 면 잠 금 을 일 으 키 기 쉽 습 니 다.
    총결산
    종합 하면 이번에 말 해 야 할 몇 가지 방법 이다.사실 모든 방법 은 같은 원리 이다.즉,호출 된 스 레 드 에서 결 과 를 막 고 리 셋 에서 함수 에서 차단 상 태 를 해제 하 는 것 이다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기