Javaマルチスレッド研究ノート_マルチスレッドの実装

マルチスレッド実装スキーム:

  1. これは、Threadクラスを継承することによって実装されます。
  2. Runnableインターフェースの実装。
  3. CallableインターフェースとFutureインターフェースを使用して達成します。

オプション1:Threadクラスを継承する

  1. Threadクラスを継承するようにMyThreadクラスを定義します。
  2. MyThreadクラスのrun()メソッドをオーバーライドします。
  3. MyThreadクラスのオブジェクトを作成します。
  4. スレッドを開始します。
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程开始了" + i);
        }
    }
}


public class Demo {
    public static void main(String[] args) {
        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        m1.start();
        m2.start();
    }
}

  • run()メソッドを書き直すのはなぜですか?

run()は、スレッドが実行する必要のあるコードをカプセル化するために使用されるためです。

  • run()メソッドとstart()メソッドの違いは何ですか?

run()は、オブジェクトを作成し、オブジェクトのメソッドを呼び出すことだけを意味し、スレッドを開始しません。

start()は、システムリソースと対話し、スレッドを開始することを意味します。


 

 方法2:Runnableインターフェースを実装する

  1. MyRunnableクラスを定義して、Runnableインターフェースを実装します。
  2. MyRunnableクラスのrun()メソッドをオーバーライドします。
  3. MyRunnableクラスのオブジェクトを作成します。
  4. Threadクラスのオブジェクトを作成し、MyRunnableクラスのオブジェクトをコンストラクターのパラメーターとして渡します。
  5. スレッドを開始します。

 

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("第二种方法实现多线程" + i);
        }
    }
}

public class Demo {
    public static void main(String[] args) {

        MyRunnable mr1 = new MyRunnable();//创建了一个参数的对象。
        Thread t1 = new Thread(mr1);//创建了一个线程对象,并把参数传递给这个线程。
        t1.start();//在线程启动之后执行的是参数里面的run()方法。

        MyRunnable mr2 = new MyRunnable();
        Thread t2 = new Thread(mr2);
        t2.start();
    }
}

 

 方法3:呼び出し可能インターフェースと将来のインターフェースを実装する

  1. MyCallableクラスを定義して、Callableインターフェースを実装します。
  2. MyCallableクラスのcall()メソッドをオーバーライドします。
  3. MyCallableクラスのオブジェクトを作成します
  4. Futureクラスの実装であるFutureTaskクラスのオブジェクトを作成し、MyCallableクラスのオブジェクトをコンストラクターのパラメーターとして渡します。
  5. Threadクラスのオブジェクトを作成し、FutureTaskオブジェクトをコンストラクターのパラメーターとして使用します。
  6. スレッドを開始します。
//这里的泛型中的数据类型和下面call()方法的返回值类型一致
//想要返回什么数据,就写对应的数据类型
public class MyCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println("第" + i + "次表白");
        }
        return "I DO.";
    }
}

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //线程开启后需要执行里面的call()方法        
        MyCallable mc = new MyCallable();
        //好比一个中间媒介
        //既可以获取线程执行完毕的结果,也可以作为参数传递给Thread对象。
        FutureTask<String> ft = new FutureTask<>(mc);
        //创建线程对象        
        Thread t = new Thread(ft);
        //开启线程
        t.start();
        System.out.println(ft.get());
    }
}

 FutureTaskクラスは、FutureインターフェースとRunnableインターフェースの両方を実装します。詳細については公式ドキュメントを確認できるため、パラメーターとしてThread構築メソッドに渡すことができます。

注: get()メソッドは、スレッドの開始後に呼び出す必要があります。


3つの方法の比較

 

  利点 不利益
インターフェイスを実装する Runnableインターフェースの実装(戻り値なし) 拡張性は強力であり、このインターフェイスの実装中に他のクラスを継承できます。 プログラミングは比較的複雑であり、Threadクラスのメソッドを直接使用することはできません。
Callableインターフェースの実装(戻り値付き)
Threadクラスを継承します

プログラミングは比較的簡単です、

Threadクラスのメソッドを直接使用できます。

 

スケーラビリティが低い、

他のクラスを継承できなくなりました。

 

 

おすすめ

転載: blog.csdn.net/qq_43191910/article/details/114818828