Maison  >  Article  >  Java  >  Explication détaillée du code de Callable et Future dans le pool de threads de concurrence Java

Explication détaillée du code de Callable et Future dans le pool de threads de concurrence Java

黄舟
黄舟original
2017-06-18 10:11:141554parcourir

Cet article présente principalement en détail le pool de threads de concurrence Callable et Future of Java, qui a une certaine valeur de référence. Les amis intéressés peuvent se référer à

Introduction à Callable et Future
<.>

Callable et Future sont une combinaison intéressante. Nous devons les utiliser lorsque nous avons besoin d'obtenir les résultats d'exécution du thread. Callable est utilisé pour produire des résultats et Future est utilisé pour obtenir des résultats.


1. Callable

Callable est une interface qui contient uniquement une méthode call(). Un Callable est une tâche qui renvoie un résultat et peut

lancer une exception. Pour faciliter la compréhension, nous pouvons comparer Callable à une interface Runnable, et la méthode call() de Callable est similaire à la méthode run() de Runnable.
Le code source de Callable est le suivant :


public interface Callable<V> {
 V call() throws Exception;
}

Explication : De là, nous peut voir que Callable prend en charge les génériques.

2. Le futur

Le futur est une interface. Il est utilisé pour représenter les résultats de calculs asynchrones. L'invention concerne des procédés permettant de vérifier si le calcul est terminé, d'attendre la fin du calcul et d'obtenir le résultat du calcul. Le code source de

Future est le suivant :


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;
}

Explication : Future est utilisé pour représenter le résultats de calculs asynchrones. Sa classe d'implémentation est FutureTask. Avant d'expliquer FutureTask, examinons d'abord le diagramme de relation entre Callable, Future et FutureTask, comme suit :

Description :

(01) RunnableFuture est une interface qui hérite des deux interfaces Runnable et Future. Le code source de RunnableFuture est le suivant :



public interface RunnableFuture<V> extends Runnable, Future<V> {
 void run();
}
(02) FutureTask implémente l'interface RunnableFuture. Par conséquent, nous disons également qu’il implémente l’interface Future.

Exemple et analyse du code source (basé sur JDK1.7.0_40)

Examinons d'abord l'utilisation de base de Callable et Future à travers un exemple, et puis analysez l'exemple de principe de mise en œuvre.


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(); 
 }
}
Résultat de l'exécution :


4950


Description du résultat :

Dans le thread principal main, créez un nouveau pool de threads via newSingleThreadExecutor(). Créez ensuite l'objet Callable c1, puis soumettez c1 au pool de threads pour traitement via pool.submit(c1), et enregistrez le résultat renvoyé dans l'objet Future f1. Ensuite, nous obtenons les résultats enregistrés dans Callable via f1.get(); enfin, nous fermons le pool de threads via pool.shutdown().


1. submit()

submit() est implémenté dans java/util/concurrent/AbstractExecutorService.java. suit :


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;
}
Explication : submit() crée l'objet RunnableFuture ftask via newTaskFor(task). Son code source est le suivant :



protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
 return new FutureTask<T>(callable);
}

2. Le constructeur de FutureTask

Le constructeur de FutureTask est le suivant :


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. La méthode run() de FutureTask
Revenons au code source de submit().

Après que newTaskFor() ait créé un objet ftask, la tâche sera exécutée viaexecute(ftask). À ce stade, ftask est exécuté en tant qu'objet Runnable, et sa méthode run() sera éventuellement appelée ; la méthode run() de ftask est implémentée dans java/util/concurrent/FutureTask.java, et le code source est le suivant. :



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);
 }
}

Explication : run() exécutera la méthode call() de l'objet Callable, et enfin enregistrez le résultat dans result. Et enregistrez le résultat via set(result).   Après avoir appelé la méthode get() de FutureTask, la valeur enregistrée par set(result) est renvoyée.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn