Javaスレッドの作成の3つの主な方法

7250 ワード

Javaスレッド作成の主な方法
一、Threadクラスの作成を継承する
Threadを継承してrun()を書き換えることで、runメソッドではスレッドがタスクを実行します.作成されたサブクラスはstart()メソッドを呼び出すことでスレッドメソッドを実行できます.
Threadによって実装されたスレッドクラスを継承することで、複数のスレッド間でスレッドクラスのインスタンス変数を共有することはできません.(異なるThreadオブジェクトを作成する必要があり、自然に共有されません)
例:
/**
 *     Thread    
 */
public class ThreadTest extends Thread{
  
  private int i = 0 ;
@Override
public void run() { for(;i<50;i++){ System.out.println(Thread.currentThread().getName() + " is running " + i ); } } public static void main(String[] args) { for(int j=0;j<50;j++){if(j=20){ new ThreadTest().start() ; new ThreadTest().start() ; } } } }

 
二、Runnableインタフェースからスレッドクラスを作成する
このメソッドは、まずクラス実装Runnableインタフェースを定義し、スレッド実行体であるrun()メソッドを書き換える必要があります.次にRunnableインプリメンテーションクラスのオブジェクトを作成し、Threadオブジェクトを作成するパラメータtargetとして、このThreadオブジェクトこそ真のスレッドオブジェクトです.Runnableインタフェースを実現するスレッドクラスは,互いにリソースを共有する.
/**
 *     Runnable        
 */
public class RunnableTest implements Runnable {
    private int i ;
    @Override
    public void run() {
        for(;i<50;i++){
            System.out.println(Thread.currentThread().getName() + " -- " + i);
        }
    }
    public static void main(String[] args) {
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName() + " -- " + i);
            if(i==20){
                RunnableTest runnableTest = new RunnableTest() ;
                new Thread(runnableTest,"  1").start() ;
                new Thread(runnableTest,"  2").start() ;
            }
        }
    }
}

 
三、CallableとFutureを使ってスレッドを作成する
Threadクラスの継承とRunnableインタフェースの実装から,上記の2つの方法はいずれも戻り値を持つことができず,放出異常を宣言することはできないことが分かる.Callableインタフェースは、Runableインタフェースのアップグレード版のように、スレッドの実行体として提供されるcall()メソッドと、戻り値を許可する2つの点を実現しています.
ただし、Callableオブジェクトは、Java 5に追加されたインタフェースであり、Runnableインタフェースのサブインタフェースではないため、Threadオブジェクトのtargetとして直接使用することはできません.この問題の解決策として、call()の戻り値を受け入れるFutureインタフェースが導入され、RunnableFutureインタフェースはFutureインタフェースとRunnableインタフェースのサブインタフェースであり、Threadオブジェクトのtargetとすることができる.さらに、Futureインタフェースは、FutureTaskという実装クラスを提供します.
FutureTaskはRunnableFutureインタフェースを実現し,Threadオブジェクトのtargetとして利用できる.
  
例:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class CallableTest {
    public static void main(String[] args) {
        CallableTest callableTest = new CallableTest() ;
        //  Callable        ,    Lambda   
        FutureTask task = new FutureTask((Callable)()->{
           int i = 0 ;
           for(;i<100;i++){
               System.out.println(Thread.currentThread().getName() + "     i   :" + i);
           }
           return i;
        });
       for(int i=0;i<100;i++){
           System.out.println(Thread.currentThread().getName()+"      i : + i");
           if(i==20){
               new Thread(task,"       ").start();
           }
       }
       try{
           System.out.println("       : " + task.get());
        }catch (Exception e){
           e.printStackTrace();
        }
    }
}

 
まとめ
上記の3つの方式により,継承クラスと実装インタフェースの2つの方式に分類できる.インタフェース実装は、継承よりも柔軟で、Javaの単一継承メカニズムに制限されません.また,インタフェースを実現することでリソースを共有でき,マルチスレッドで同じリソースを処理する場合に適している.スレッドの知識は豊富で複雑で、より多くの詳細を学ぶ必要があります.