マルチスレッド実装スキーム:
- これは、Threadクラスを継承することによって実装されます。
- Runnableインターフェースの実装。
- CallableインターフェースとFutureインターフェースを使用して達成します。
オプション1:Threadクラスを継承する
- Threadクラスを継承するようにMyThreadクラスを定義します。
- MyThreadクラスのrun()メソッドをオーバーライドします。
- MyThreadクラスのオブジェクトを作成します。
- スレッドを開始します。
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インターフェースを実装する
- MyRunnableクラスを定義して、Runnableインターフェースを実装します。
- MyRunnableクラスのrun()メソッドをオーバーライドします。
- MyRunnableクラスのオブジェクトを作成します。
- Threadクラスのオブジェクトを作成し、MyRunnableクラスのオブジェクトをコンストラクターのパラメーターとして渡します。
- スレッドを開始します。
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:呼び出し可能インターフェースと将来のインターフェースを実装する
- MyCallableクラスを定義して、Callableインターフェースを実装します。
- MyCallableクラスのcall()メソッドをオーバーライドします。
- MyCallableクラスのオブジェクトを作成します
- Futureクラスの実装であるFutureTaskクラスのオブジェクトを作成し、MyCallableクラスのオブジェクトをコンストラクターのパラメーターとして渡します。
- Threadクラスのオブジェクトを作成し、FutureTaskオブジェクトをコンストラクターのパラメーターとして使用します。
- スレッドを開始します。
//这里的泛型中的数据类型和下面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クラスのメソッドを直接使用できます。 |
スケーラビリティが低い、 他のクラスを継承できなくなりました。
|