이 기사에서는 주로 Java 동시성 스레드 풀의 Callable 및 Future를 자세히 소개하며, 관심 있는 친구는
Introduction to Callable and Future
Callable과 Future가 더 흥미로운 조합을 참조할 수 있습니다. 스레드의 실행 결과를 가져와야 할 때 이를 사용해야 합니다. Callable은 결과를 생성하는 데 사용되고 Future는 결과를 얻는 데 사용됩니다.
1. Callable
Callable은 call() 메소드만 포함하는 인터페이스입니다. Callable은 결과를 반환하고 예외를 발생시킬 수 있는 작업입니다.
이해를 돕기 위해 Callable을 Runnable 인터페이스와 비교할 수 있으며 Callable의 call() 메서드는 Runnable의 run() 메서드와 유사합니다.
Callable의 소스 코드는 다음과 같습니다.
public interface Callable<V> { V call() throws Exception; }
설명: 이를 통해 Callable이 제네릭을 지원한다는 것을 알 수 있습니다.
2. Future
미래는 인터페이스입니다. 비동기 계산 결과를 나타내는 데 사용됩니다. 계산이 완료되었는지 확인하고, 계산이 완료될 때까지 기다리고, 계산 결과를 얻을 수 있는 방법이 제공됩니다.
Future의 소스 코드는 다음과 같습니다.
public interface Future<V> { // 试图取消对此任务的执行。 boolean cancel(boolean mayInterruptIfRunning) // 如果在任务正常完成前将其取消,则返回 true。 boolean isCancelled() // 如果任务已完成,则返回 true。 boolean isDone() // 如有必要,等待计算完成,然后获取其结果。 V get() throws InterruptedException, ExecutionException; // 如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。 V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
설명: Future는 비동기 계산의 결과를 나타내는 데 사용됩니다. 구현 클래스는 FutureTask입니다. 먼저 Callable, Future 및 FutureTask 간의 관계 다이어그램을 살펴보겠습니다.
설명:
(01) RunnableFuture는 인터페이스입니다. Runnable과 Future의 두 인터페이스를 상속합니다. RunnableFuture의 소스 코드는 다음과 같습니다.
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
(02) FutureTask는 RunnableFuture 인터페이스를 구현합니다. 따라서 Future 인터페이스를 구현한다고도 합니다.
예제 및 소스코드 분석 (JDK1.7.0_40 기준)
먼저 예제를 통해 Callable과 Future의 기본 사용법을 살펴본 후 예제의 구현 원리를 분석해 보겠습니다.
import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutionException; class MyCallable implements Callable { @Override public Integer call() throws Exception { int sum = 0; // 执行任务 for (int i=0; i<100; i++) sum += i; //return sum; return Integer.valueOf(sum); } } public class CallableTest1 { public static void main(String[] args) throws ExecutionException, InterruptedException{ //创建一个线程池 ExecutorService pool = Executors.newSingleThreadExecutor(); //创建有返回值的任务 Callable c1 = new MyCallable(); //执行任务并获取Future对象 Future f1 = pool.submit(c1); // 输出结果 System.out.println(f1.get()); //关闭线程池 pool.shutdown(); } }
실행 결과:
4950
결과 설명:
메인 스레드 메인에서 newSingleThreadExecutor()를 통해 새 스레드 풀을 생성합니다. 그런 다음 Callable 객체 c1을 생성한 다음 pool.submit(c1)을 통해 처리하기 위해 스레드 풀에 c1을 제출하고 반환된 결과를 Future 객체 f1에 저장합니다. 그런 다음 f1.get()을 통해 Callable에 저장된 결과를 얻고 마지막으로 pool.shutdown()을 통해 스레드 풀을 닫습니다.
1.submit()
submit()은 java/util/concurrent/AbstractExecutorService.java에서 구현됩니다. 소스 코드는 다음과 같습니다.
public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); // 创建一个RunnableFuture对象 RunnableFuture<T> ftask = newTaskFor(task); // 执行“任务ftask” execute(ftask); // 返回“ftask” return ftask; }
설명: submit()이 newTaskFor(를 통과합니다. 작업) RunnableFuture 개체 ftask를 생성했습니다.
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); }
2. FutureTask의 constructor
FutureTask 생성자는 다음과 같습니다.
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); // callable是一个Callable对象 this.callable = callable; // state记录FutureTask的状态 this.state = NEW; // ensure visibility of callable }
3. ()방법
하자 계속해서 submit()의 소스 코드로 돌아가세요.
newTaskFor()가 새로운 ftask 객체를 생성한 후, 실행(ftask)을 통해 작업이 실행됩니다. 이때 ftask는 Runnable 객체로 실행되며 결국 해당 run() 메서드가 호출되며 ftask의 run() 메서드는 java/util/concurrent/FutureTask.java에 구현되어 있으며 소스 코드는 다음과 같습니다. :
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { // 将callable对象赋值给c。 Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { // 执行Callable的call()方法,并保存结果到result中。 result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } // 如果运行成功,则将result保存 if (ran) set(result); } } finally { runner = null; // 设置“state状态标记” int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
설명: run()은 Callable 객체의 call() 메소드를 실행하고 최종적으로 결과를 result에 저장하고 set(result)를 통해 결과를 저장합니다.
FutureTask의 get() 메소드를 호출한 후 set(result)에 의해 저장된 값이 반환됩니다.
위 내용은 Java 동시성 스레드 풀의 Callable 및 Future에 대한 자세한 코드 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!