>  기사  >  Java  >  Java의 Future 패턴에 대한 자세한 설명

Java의 Future 패턴에 대한 자세한 설명

怪我咯
怪我咯원래의
2017-06-30 10:42:113553검색

아래 편집기에서는 Java의 Future 모드에 대한 옛날 이야기를 들려줄 것입니다. 에디터가 꽤 좋다고 생각해서 지금 공유해서 참고용으로 올려보겠습니다. 에디터와 함께 구경하러 가세요

jdk1.7.0_79

이 글은 사실 위의 글의 연속이거나 속편입니다. ThreadPoolExecutor 스레드 풀의 submit 메소드에 대해 간단히 이야기해 보세요. " 보충하세요. FutureTask는 위에서 언급한 submit 메소드에 나타났는데, 이로 인해 저는 중단하고 Java의 Future 모드로 전환해야 했습니다.

Future는 동시 프로그래밍의 디자인 패턴입니다. 멀티스레딩의 경우 스레드 A는 스레드 B의 결과를 기다려야 합니다. 항상 B를 기다릴 필요는 없습니다. B가 그것을 가질 때까지 기다리십시오. 그런 다음 결과 후에 실제 결과를 얻으십시오.

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(callable); //主线程需要callable线程的结果,先拿到一个未来的Future
System.out.println(future.get()); //有了结果后再根据get方法取真实的结果,当然如果此时callable线程如果没有执行完get方法会阻塞执行完,如果执行完则直接返回结果或抛出异常

즉, Future는 비동기 계산의 결과를 나타냅니다.

위는 Future 모드의 실행 원리를 나타냅니다. 온라인 예제에 따르면 Future 모드를 직접 구현할 수 있습니다.

package com.future;

/**
 * 数据结果
 * Created by yulinfeng on 6/18/17.
 */
public interface Data {
 String getResult() throws InterruptedException;
}
package com.future;

/**
 * 结果的真实计算过程
 * Created by yulinfeng on 6/18/17.
 */
public class RealData implements Data {
 protected String data;

 public RealData(String data) {
  try {
   System.out.println("正在计算结果");
   Thread.sleep(3000);  //模拟计算
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  this.data = data + “ world”;
 }

 public String getResult() throws InterruptedException {
  return data;
 }
}
package com.future;

/**
 * 真实结果RealData的代理
 * Created by yulinfeng on 6/18/17.
 */
public class FutureData implements Data {
 RealData realData = null; //对RealData的封装,代理了RealData
 boolean isReady = false; //真实结果是否已经准备好

 public synchronized void setResultData(RealData realData) {
  if (isReady) {
   return;
  }
  this.realData = realData;
  isReady = true;
  notifyAll(); //realData已经被注入到了futureData中,通知getResult方法
 }

 public synchronized String getResult() throws InterruptedException {
  if (!isReady) {
   wait();  //数据还未计算好,阻塞等待
  }
  return realData.getResult();
 }
}
package com.future;

/**
 * Client主要完成的功能包括:1. 返回一个FutureData;2.开启一个线程用于构造RealData
 * Created by yulinfeng on 6/18/17.
 */
public class Client {

 public Data request(final String string) {
  final FutureData futureData = new FutureData();

  /*计算过程比较慢,单独放到一个线程中去*/
  new Thread(new Runnable() {

   public void run() {
    RealData realData = new RealData(string);
    futureData.setResultData(realData);
   }
  }).start();

  return futureData; //先返回一个“假”的futureData
 }
}
/**
 * 负责调用Client发起请求,并使用返回的数据。
 * Created by yulinfeng on 6/18/17.
 */
public class Main {
 public static void main(String[] args) throws InterruptedException {
  Client client = new Client();
  System.out.println("准备计算结果");
  Data data = client.request("hello"); //立即返回一个“假”的futureData,可以不用阻塞的等待数据返回,转而执行其它任务
  System.out.println("执行其它任务");
  Thread.sleep(3000);  //模拟执行其它任务
  System.out.println("数据的计算结果为:" + data.getResult());
 }
}

위 프로그램에서 Future 모드의 구현을 주의 깊게 읽어보면 Future 모드가 비동기 요청과 Proxy 모드의 조합이라는 것을 어렵지 않게 찾을 수 있습니다. 물론 Future 모드는 JDK에서 구현되었습니다.

RealData 클래스 수정:

package com.future;

import java.util.concurrent.Callable;

/**
 * 结果的真实计算过程
 * Created by yulinfeng on 6/18/17.
 */
public class RealData2 implements Callable<String> {
 protected String data;

 public RealData2(String data) {
  this.data = data;
 }
 public String call() throws Exception {
  try {
   System.out.println("正在计算结果");
   Thread.sleep(2000);  //模拟计算结果
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  this.data = data + " world";
  return data;
 }
}

Main 테스트 클래스 수정:

package com.future;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 负责调用Executor的submit,并使用返回的数据。
 * Created by yulinfeng on 6/18/17.
 */
public class Main2 {

 public static void main(String[] args) throws InterruptedException, ExecutionException {
  ExecutorService client = Executors.newSingleThreadExecutor(); //类似Client
  System.out.println("准备计算结果");
  Future<String> data = client.submit(new RealData2("hello")); //类似Client.request
  System.out.println("执行其它任务");
  Thread.sleep(3000);
  System.out.println("数据的计算结果为:" + data.get());
 }
}

이제 위에서 해결되지 않은 AbstractExecutorService#submit 메소드로 돌아갑니다.

위의 Client#request 메소드와 유사하게 FutureData 인스턴스는 먼저 Client#request에서 생성되고 FutureTask 인스턴스는 AbstractExecutorService#submit에서 생성됩니다. 그런 다음 Client#request는 작업의 비동기 실행을 위한 새 스레드를 생성하고 직접 FutureData를 반환하고 AbstractExecutorService#submit에서 작업도 실행 메소드로 넘겨져 FutureTask를 직접 반환합니다. 물론 JDK에서 Future 모드를 구현하는 것은 더 복잡합니다.

"ThreadPoolExecutor 스레드 풀 원리 및 실행 메서드"에서 실행 메서드를 설명했습니다. ThreadPoolExecutor$Worker#runWorker 메서드의 1145번째 줄은 작업 작업에 대한 호출입니다.

//ThreadPoolExecutor$Worker#runWorker
task.run();

submit 호출은 run 메서드를 실행합니다. , 실제로 실행되는 것은 FutureTask의 run 메소드입니다. FutureTask#run에서는 Callable 유형의 작업을 비동기적으로 실행하고 결과를 저장하는 것을 볼 수 있습니다.

위 내용은 Java의 Future 패턴에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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