Java의 util을 간략하게 분석합니다.concurrent.Future 인터페이스

4741 단어 JavaFuture
단일 스레드 응용 프로그램에서 계산이 끝나야만 결과를 되돌릴 수 있는 방법을 호출합니다(IOUtils.toString ()comes from Apache Commons IO).
 

public String downloadContents(URL url) throws IOException {
  try(InputStream input = url.openStream()) {
    return IOUtils.toString(input, StandardCharsets.UTF_8);
  }
}
 
//...
 
final Future<String> contents = downloadContents(new URL("http://www.example.com"));
다운로드 콘텐츠 () 는 무해해 보이지만 임의의 시간이 필요합니다.또한 지연을 줄이기 위해 결과를 기다리는 동안 다른 일을 동시에 독립적으로 처리해야 할 수도 있다.이전에 새로운 라인을 시작하거나 결과를 기다릴 수도 있습니다. (공유 메모리, 자물쇠, 엉망진wait ()/notify () 맞습니다.)
Future 모드를 사용하면 다음과 같이 밝아집니다.
 

public static Future<String> startDownloading(URL url) {
  //...
}
 
final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com"));
//other computation
final String contents = contentsFuture.get();
우리는 곧 startDownloading () 을 실현할 것입니다. startDownloading () 은 막히지 않고 외부 사이트의 응답을 기다리는 것입니다. 이 원칙을 이해하는 것이 중요합니다.반대로 빠르게 되돌아오면 경량급의 Future < String > 대상을 되돌려줍니다.이 대상은promise입니다. 그러면 앞으로 문자열 형식이 사용될 것입니다. 우리는 언제 사용될지 모르지만, 결과가 돌아올 때까지 이 인용을 보류할 것입니다. 당신은 Future를 통과할 수 있습니다.get () 에서 가져옵니다.다시 말하면 Future는 에이전트나 대상의 포장이지 실제 목표 대상이 아니다.일단 비동기적인 계산이 완성되면, 너는 그것을 추출할 수 있다.그러면 Future는 어떤 인터페이스를 제공합니까?
Future.get () 가 가장 중요한 방법입니다.약속한 결과가 사용 가능한 상태가 될 때까지 막고 기다립니다. 따라서 이 문자열이 필요하면 get () 방법을 사용해서 기다립니다.시간 초과 파라미터를 받아들이는 리셋 버전이 하나 더 있습니다. 문제가 생기면 계속 기다릴 필요가 없습니다. 설정 시간이 지나면 Timeout Exception을 던집니다.
어떤 경우, 당신은 끊임없이 Future가 사용할 수 있는지 몰래 보고 싶을 수도 있습니다.이것은 isDone () 을 통해 완성할 수 있습니다.사용자가 어떤 비동기적인 계산을 기다리고 있는 상황을 상상해 보세요. 이런 상황을 알게 하고 다른 계산을 하고 싶습니다.
 

final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com"));
while (!contentsFuture.isDone()) {
  askUserToWait();
  doSomeComputationInTheMeantime();
}
contentsFuture.get();
마지막 미래.get() 호출된 내용은 Future 때문에 바로 되돌아올 수 있습니다. 막히지 않습니다.isDone () 이 true 를 반환했습니다.만약 당신이 이 모드를 따른다면, 초당 백만 번의 교체 대기와 isDone () 호출에 바쁘지 않을 것입니다.
futrues를 취소하는 것이 마지막입니다. 아직 덮어쓰지 않은 것입니다.비동기적인 작업을 시작하고 2초 후에 우리가 포기하거나 오류를 전달하거나 임시 방안으로 해결할 수 있는 시간을 기다릴 수밖에 없다고 상상해 보세요.그러나 당신은 좋은 시민입니다. 당신은 이future 대상에게 말해야 합니다. 저는 당신을 필요로 하지 않습니다. 상관하지 마세요.그러면 당신은 유행이 지난 임무를 멈추고 자원을 절약할 수 있습니다.구문은 간단합니다.
 

contentsFuture.cancel(true);  //meh...
우리는 모두 숨겨진, 볼 유형의 매개 변수를 좋아한다. 그렇지?취소는 두 가지 방식으로 이루어질 수 있다. 작업이 시작되기 전에false 파라미터를 전달함으로써 취소할 수 있다. 전제는 Future가 표현한 결과 계산이 시작되기 전이다.일단 Callable하면.call () 이 절반까지 실행되었습니다. 그러면 끝내고 싶습니다. true를 전달하면 Future.call () 은 실행 중인 작업을 끊으려는 침입성을 가지고 있습니다.너는 이렇게 하는 것이 좋다고 생각하니?Thread와 같이 Interrupted Exception이라는 평판이 엉망인 이상한 방법을 내놓는 현상.sleep(), Object.wait(),Condition.await(), 등, 심지어 Future까지.get(). 만약 당신이 이 방법에 막혀 있고 호출을 취소하기로 결정한다면, 그들은 의심할 여지없이 Interruption Exception을 던지고, 현재 실행 중인 작업을 중단할 사람을 보낼 것이다.
그래서 우리는 이제 Future가 무엇인지 알게 되었다. - 하나의 자리 표시자, 당신은 미래에 목표 대상을 얻을 수 있다.마치 차 한 대에 대해 아직 만들어지지 않은 열쇠와 같다.그러나 당신은 어떻게 해야만 응용 프로그램에서 Future의 실례를 얻을 수 있습니까?두 가지 가장 일반적인 자원은 스레드 탱크와 비동기 방법 (스레드 탱크 지원) 이다.따라서 startDownloading() 메서드는 다음과 같이 다시 쓸 수 있습니다.
 

private final ExecutorService pool = Executors.newFixedThreadPool(10);
 
public Future<String> startDownloading(final URL url) throws IOException {
  return pool.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
      try (InputStream input = url.openStream()) {
        return IOUtils.toString(input, StandardCharsets.UTF_8);
      }
    }
  });
}
비록 대량의 번거로운 문법 문제가 있지만 기본적인 사상은 간단하다. 장시간 운행이 필요한 계산을 호출 가능한 에 포장하고submit()에서 스레드 탱크에 포장하는 것이다. 이 스레드 탱크는 10개의 스레드를 포함한다.제출 후 Future < String > 의 구현으로 돌아갑니다. 마치 어떤 방식으로 당신의 작업과 스레드 탱크에 연결되는 것과 같습니다.분명히 당신의 임무는 즉각 실행되지 않을 것입니다. 반대로 하나의 대기열에 놓여 있다가 라인에 끌려나올 것입니다. 지금은 cancel () 의 두 가지 특별한 의미가 무엇인지 알아야 합니다. 대기열에 머무르는 임무를 취소할 수도 있고, 이미 실행된 임무를 취소할 수도 있지만, 이것은 비교적 복잡한 일입니다.
너는 스프링에서 EJB와 Future를 만날 수도 있다.예를 들어 Spring 프레임워크에 @Async 메모를 추가할 수 있습니다.

@Async
public Future<String> startDownloading(final URL url) throws IOException {
  try (InputStream input = url.openStream()) {
    return new AsyncResult<>(
        IOUtils.toString(input, StandardCharsets.UTF_8)
    );
  }
}

주의, 우리는 간단하게 포장 결과를 통해 AsyncResult를 통해 Future를 실현하지만, 이 방법 자체는 스레드 탱크와 상호작용하거나 비동기적으로 처리하지 않습니다.잠시 후 Spring은 startDownloading () 을 위한 모든 호출을 에이전트하고 온라인 플로팅 탱크에서 실행합니다.EJB에서 같은 특성은 @Asynchronousannotation을 추가하여 완성합니다.

좋은 웹페이지 즐겨찾기