>  기사  >  Java  >  Java의 콜백 메커니즘에 대한 자세한 설명

Java의 콜백 메커니즘에 대한 자세한 설명

高洛峰
高洛峰원래의
2017-01-24 11:52:351353검색

모듈 간에는 항상 특정 인터페이스가 있습니다. 호출 메서드의 관점에서 보면 동기 호출, 콜백 및 비동기 호출의 세 가지 범주로 나눌 수 있습니다. 다음에서는 콜백 메커니즘에 대해 자세히 중점적으로 설명합니다.

1. 개요

Java의 콜백 메커니즘은 비교적 일반적인 메커니즘이지만 일부 대규모 프로그램에서는 콜백 메커니즘이 덜 사용될 수 있습니다. 프레임워크의 모든 곳에서 발견됩니다. 이 기사에서는 몇 가지 구체적인 예를 통해 Java의 콜백 메커니즘에 천천히 접근할 것입니다.

2. 콜백

콜백이라 불리는 것: 클래스 A가 클래스 B의 메서드 C를 호출한 다음, 클래스 B가 차례로 클래스 A의 메서드를 호출합니다. D, 이 메서드 D를 콜백 메서드라고 합니다. 실제 사용에서는 다음과 같은 다양한 콜백 형태가 있습니다.

2.1 동기 콜백

여기서는 이런 상황을 가정합니다.

A사의 B 이사가 부하직원(프로젝트 매니저 C)에게 설문조사를 하라고 했으나 C사가 직접 할 필요는 없었습니다. 관리자 C에게 아래에 프로그래머 D가 작업을 완료하도록 주선해 달라고 요청할 수 있습니다. C 과장은 프로그래머 D를 찾아 이제 연구 과제를 완료해야 한다고 말했습니다. 그리고 관리자 C에게 설문조사 결과를 알려주세요. 문제가 있으면 계속 진행해야 합니다. 여기서 C는 D에게 작업을 요청하고 D는 그 결과를 C와 전달해야 하기 때문입니다. 이것이 콜백 모델입니다. 다음은 일반 콜백의 클래스 다이어그램입니다.

Java의 콜백 메커니즘에 대한 자세한 설명

먼저 콜백 인터페이스 CallbackInterface

CallbackInterface.java

가 필요합니다.
public interface CallbackInterface {
  public boolean check(int result);
}


백그라운드에서 프로그래머 D는 결과를 프로젝트 관리자 C와 통신하려고 하므로 여기의 프로젝트 관리자는 위의 콜백 인터페이스를 구현해야 합니다.

Manager.java

public class Manager implements CallbackInterface {
 
  private Programmer programmer = null;
 
  public Manager(Programmer _programmer) {
    this.programmer = _programmer;
  }
 
  /**
   * 用于 Boss 下达的委托
   */
  public void entrust() {
    arrange();
  }
 
  // 进行安排下属进行 study 工作
  private void arrange() {
    System.out.println("Manager 正在为 Programmer 安排工作");
    programmer.study(Manager.this);
    System.out.println("为 Programmer 安排工作已经完成,Manager 做其他的事情去了。");
  }
 
  @Override
  public boolean check(int result) {
    if (result == 5) {
      return true;
    }
    return false;
  }
 
}


프로그래머 D의 경우 관리자 C에 대한 참조를 보유해야 관리자 C와 통신할 수 있습니다. 그를. 그런데 이는 B 과장이 C 과장에게 정리를 부탁한 일이다. 즉, 여기에는 관리자 B1, B2 등 다른 관리자도 허용될 수 있습니다. 관리자가 콜백 인터페이스를 구현했기 때문에 프로그래머 D는 이 인터페이스를 직접 보유할 수 있습니다. 다음과 같습니다:

Programmer.java

public class Programmer {
 
  public void study(CallbackInterface callback) {
    int result = 0;
    do {
      result++;
      System.out.println("第 " + result + " 次研究的结果");
    } while (!callback.check(result));
 
    System.out.println("调研任务结束");
  }
}

클라이언트 테스트와 동일하므로 감독에게는 더 간단하고 명확합니다.

Boss.java

public class Boss {
 
  public static void main(String[] args) {
    Manager manager = new Manager(new Programmer());
    manager.entrust();
  }
}

실행 결과:

관리자가 프로그래머를 위한 작업을 준비 중
1차 연구 결과
2차 연구결과
3차 연구결과
4차 연구결과
5차 연구결과
연구과제 종료
프로그래머 업무 정리 완료, 관리자 갔습니다 다른 일을 하려고.

2.2 비동기 콜백

그래도 위의 예에서는 프로젝트 관리자가 항상 연구 결과를 기다릴 수는 없습니다. 그러나 당신에게 이 일을 맡기면 그는 그것에 대해 신경 쓰지 않을 것이고 당신은 당신의 일을 할 것입니다. 따라서 콜백 함수는 비동기적으로 처리되어야 합니다.
그래서 여기에서 Programmer 클래스의 코드를 다음과 같이 수정해야 합니다.

Programmer.java

public class Programmer {
 
  public Programmer() {
  }
 
  public void study(CallbackInterface callback) {
    new StudyThread(callback).start();
  }
 
  // --------------------------- Programmer 正在做的工作 ---------------------------
 
  class StudyThread extends Thread {
 
    CallbackInterface callback = null;
 
    public StudyThread(CallbackInterface _callback) {
      callback = _callback;
    }
 
    @Override
    public void run() {
      int result = 0;
      do {
        result++;
        System.out.println("第 " + result + " 次研究的结果");
      } while (!callback.check(result));
 
      System.out.println("调研任务结束");
    }
  }
}

실행 결과 :

관리자가 프로그래머 작업을 준비 중입니다.
프로그래머 작업 정리가 완료되었으며 관리자는 다른 작업을 하러 나갔습니다.
1차 연구 결과
2차 연구 결과
3차 연구 결과
4차 연구 결과
5차 연구 결과
연구과제 종료

2.3 클로저와 콜백

클로저는 생성된 범위의 일부 정보를 기록하는 호출 가능한 개체입니다.

2.3.1 일반 통화

먼저 일반적인 상황에서 통화가 어떻게 수행되는지 살펴보겠습니다.
Incrementable.java

interface Incrementable {
  void increment();
}

공통 인터페이스입니다(그냥 일반 호출에서는 공통 인터페이스이고, 콜백에서는 콜백 인터페이스입니다. 쉬울 겁니다. 이해하기 위해).

Callee1.java

class Callee1 implements Incrementable {
 
  private int i = 0;
 
  @Override
  public void increment() {
    i++;
    System.out.println(i);
  }
 
}

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();
    callee1.increment();
  }
}

Callbacks는 테스트 클라이언트 클래스이므로 할 말이 많지 않습니다. 위의 코드를 직접 보세요.

2.3.2 콜백 사전 테스트

위의 일반적인 호출에 대해서는 말할 것도 없습니다. 일반 Java 프로그래머라면 별 생각 없이 할 수 있는 일이기 때문입니다. .

이제 콜백을 구성하려면 프로그램 구조나 논리적 사고를 기준으로 단 하나의 호출 수신자(콜백 개체 Callee1)만 갖는 것은 불가능합니다. 호출자는 다음과 같이 작성할 수 있습니다:

Caller.java

class Caller {
 
  private Incrementable callbackReference;
 
  public Caller(Incrementable _callbackReference) {
    callbackReference = _callbackReference;
  }
 
  void go() {
    callbackReference.increment();
  }
}

여기서 호출자는 콜백 인터페이스 callbackReference에 대한 참조를 보유합니다. 위에서 언급했듯이 프로그래머는 프로젝트 관리자에 대한 참조를 보유해야 이 참조를 통해 프로젝트 관리자와 통신할 수 있습니다. 여기서 callbackReference도 이 역할을 합니다.

이제 테스트 클래스 작성을 살펴보겠습니다.

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();   
    Caller caller1 = new Caller(callee1);
    caller1.go();
  }
}

对于到目前为止的程序代码,完全可以对比上面项目经理安排程序员调研技术难题的代码。有异曲同工之妙。

2.3.3 闭包回调

相比于正常的回调,闭包回调的核心自然是在于闭包,也就是对作用域的控制。 
现在假设有一个用户(其他程序员)自定义了一个 MyInCrement 类,同时包含了一个 increment 的方法。如下:

class MyInCrement {
 
  public void increment() {
    System.out.println("MyCrement.increment");
  }
 
  static void f(MyInCrement increment) {
    increment.increment();
  }
}

另外有一个类 Callee2 继承自上面这个类:

class Callee2 extends MyInCrement {
 
  private int i = 0;
 
  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
}

显而易见这里如果要调用 increment() 方法,就变成了一般的函数调用了。所以这里我们需要修改上面的 Callee2 类,修改的目标就是让 Callee2 类可以兼容 MyInCrement 类的 increment() 方法和 Incrementable 的 increment() 方法。修改后:

class Callee2 extends MyInCrement {
 
  private int i = 0;
 
  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
 
  private class Closure implements Incrementable {
 
    @Override
    public void increment() {
      Callee2.this.increment();
    }
  }
 
  Incrementable getCallbackReference() {
    return new Closure();
  }
}

注意,这里的 Closure 类是一个私有的类,这是一个闭包的要素。因为 Closure 类是私有的,那么就要有一个对外开放的接口,用来对 Closure 对象的操作,这里就是上面的 getCallbackReference() 方法。 Caller 类则没有改变。 
对于测试客户端就直接看代码吧:

public class Callbacks {
  public static void main(String[] args) {   
    Callee2 callee2 = new Callee2();
    Caller caller2 = new Caller(callee2.getCallbackReference());
    caller2.go();
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多Java의 콜백 메커니즘에 대한 자세한 설명相关文章请关注PHP中文网!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.