Maison  >  Article  >  Java  >  Comment implémenter le multithreading en Java ? (exemple de code)

Comment implémenter le multithreading en Java ? (exemple de code)

青灯夜游
青灯夜游avant
2019-02-26 16:47:164813parcourir

Le contenu de cet article est de savoir comment implémenter le multi-threading en Java ? (Exemple de code) a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère que cela vous sera utile.

Méthode 1 : Hériter de la classe et remplacer la méthode run()

Nous remplaçons run() dans la sous-classe de la classe Thread créée , ajoutez simplement le code à exécuter par le thread.

Ce qui suit est un exemple :

 public class MyThread extends Thread
  {
   int count= 1, number;
   public MyThread(int num)
   {
    number = num;
    System.out.println
    ("创建线程 " + number);
   }
   public void run() {
    while(true) {
     System.out.println
      ("线程 " + number + ":计数 " + count);
     if(++count== 6) return;
    }
  }
  public static void main(String args[])
  {
   for(int i = 0;i 〈 5; i++) new MyThread(i+1).start();
  }
 }

Cette méthode est simple et claire, et correspond aux habitudes de chacun. Cependant, elle présente aussi un gros défaut, c'est-à-dire. , si notre classe Si vous avez déjà hérité d'une classe (par exemple, l'applet doit hériter de la classe Applet ), vous ne pouvez plus hériter du Thread classe À ce stade, si nous ne voulons pas créer une nouvelle classe, que dois-je faire ?

Autant explorer une nouvelle méthode : on ne crée pas de sous-classe de la classe Thread, mais on l'utilise directement, on ne peut alors que Passez notre méthode en paramètre à une instance de la classe Thread , un peu comme une fonction de rappel. Mais Java n'a pas de pointeur, on ne peut passer qu'une instance de la classe qui contient cette méthode.
Alors comment restreindre cette classe pour inclure cette méthode ? En utilisant l'interface bien sûr ! (Bien que les classes abstraites puissent également être satisfaites, elles nécessitent un héritage. La raison pour laquelle nous adoptons cette nouvelle méthode n'est-elle pas simplement pour éviter les restrictions causées par l'héritage ?)


Java

fournit l'interface

java.lang.Runnable prend en charge cette méthode.

Méthode 2 : Implémenter l'interface Runnable Runnable

interface Il n'y a qu'une seule méthode

run(), nous déclarons notre classe pour implémenter l'interface Runnable et fournissons cette méthode pour convertir notre code du fil En l'écrivant, cette partie de la tâche est terminée. Mais l'interface Runnable n'a aucun support pour les threads. Il faut également créer une instance de la classe Thread, ce qui est fait. via ThreadConstructeur de classe public Thread(Runnable target); à implémenter. Voici un exemple :

public class MyThread implements Runnable
  {
   int count= 1, number;
   public MyThread(int num)
   {
    number = num;
    System.out.println("创建线程 " + number);
   }
   public void run()
   {
    while(true)
    {
     System.out.println
     ("线程 " + number + ":计数 " + count);
     if(++count== 6) return;
    }
   }
   public static void main(String args[])
   {
    for(int i = 0; i 〈 5;i++) new Thread(new MyThread(i+1)).start();
   }
  }
À proprement parler, il est également envisageable de créer une instance de la sous-classe

Thread, mais il faut noter que la sous-classe must Il n'y a pas de couverture de la méthode Thread de la classe run , sinon le thread exécutera le run de la sous-classe , au lieu de la méthode run de la classe que nous utilisons pour implémenter l'interface Runnable , vous pouvez je souhaite expérimenter cela une fois.

L'utilisation de l'interface

Runnable pour implémenter le multi-threading nous permet de contenir tout le code dans une seule classe, ce qui est bénéfique pour l'encapsulation. we Un seul ensemble de codes peut être utilisé. Si vous souhaitez créer plusieurs threads et que chaque thread exécute des codes différents, vous devez toujours créer des classes supplémentaires. Si tel est le cas, dans la plupart des cas, il peut être préférable d'hériter directement de. plusieurs classes Thread Livré de manière compacte.

方法三、使用ExecutorService、Callable、Future实现有返回结果的多线程

ExecutorServiceCallableFuture这个对象实际上都是属于Executor框架中的功能类。想要详细了解Executor框架的可以访问http://www.javaeye.com/topic/366591 ,这里面对该框架做了很详细的解释。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。

可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在JDK1.5下验证过没问题可以直接使用。代码如下:

import java.util.concurrent.*;  
import java.util.Date;  
import java.util.List;  
import java.util.ArrayList;  

@SuppressWarnings("unchecked")  

public class Test {  
public static void main(String[] args) throws ExecutionException,  
    InterruptedException {  
   System.out.println("----程序开始运行----");  
   Date date1 = new Date();  
   int taskSize = 5;  
   // 创建一个线程池  
   ExecutorService pool = Executors.newFixedThreadPool(taskSize);  
   // 创建多个有返回值的任务  
   List list = new ArrayList();  
   for (int i = 0; i < taskSize; i++) {  
    Callable c = new MyCallable(i + " ");  
    // 执行任务并获取Future对象  
    Future f = pool.submit(c);  
    // System.out.println(">>>" + f.get().toString());  
    list.add(f);  
   }  
   // 关闭线程池  
   pool.shutdown();  
   // 获取所有并发任务的运行结果  
   for (Future f : list) {  
    // 从Future对象上获取任务的返回值,并输出到控制台  
    System.out.println(">>>" + f.get().toString());  
   }  
   Date date2 = new Date();  
   System.out.println("----程序结束运行----,程序运行时间【"  
     + (date2.getTime() - date1.getTime()) + "毫秒】");  
}  
}  
class MyCallable implements Callable {  
private String taskNum;  
MyCallable(String taskNum) {  
   this.taskNum = taskNum;  
}  
public Object call() throws Exception {  
   System.out.println(">>>" + taskNum + "任务启动");  
   Date dateTmp1 = new Date();  
   Thread.sleep(1000);  
   Date dateTmp2 = new Date();  
   long time = dateTmp2.getTime() - dateTmp1.getTime();  
   System.out.println(">>>" + taskNum + "任务终止");  
   return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";  
}  
}

代码说明:

上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。

public static ExecutorService newFixedThreadPool(int nThreads)

创建固定数目线程的线程池。

public static ExecutorService newCachedThreadPool()

创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

public static ExecutorService newSingleThreadExecutor()

创建一个单线程化的Executor

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

综上所述,以上方法各有千秋,大家可以灵活运用。

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer