マルチスレッドを実現する2つの方法の比較分析

Threadクラスを直接継承し、Runnableインターフェイスを実装するとマルチスレッドを実現できるため、実際のアプリケーションでマルチスレッドを実装するこれら2つの方法の違いは何ですか?次に、アプリケーションシナリオを分析します。

チケットオフィスに、特定の日に特定の列車の100枚のチケットを販売できる4つのウィンドウがあるとします。このとき、100枚のチケットは共有リソースと見なすことができ、4つのチケットウィンドウで4つのスレッドを作成する必要があります。ウィンドウのチケット販売をより直感的に表示するために、ThreadのcurrentThread()メソッドを介して現在のスレッドのインスタンスオブジェクトを取得し、getName()を呼び出してスレッドの名前を取得できます。次に、まずThreadクラスを継承して複数のスレッドの作成を実現します。

public class Example1 {
    
    
	public static void main(String[] args) {
    
    
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
	}
}
class TicketWindow extends Thread {
    
    
	private int tickets = 100;
	public void run() {
    
    
		while (true) {
    
        // 通过死循环语句打印语句
			if (tickets > 0) {
    
    
				Thread th = Thread.currentThread(); // 获取当前线程
				String th_name = th.getName();       // 获取当前线程的名字
				System.out.println(th_name + " 正在发售第 " + tickets--+" 张票 ");
			}
		}
	}
}

実行結果:
ここに画像の説明を挿入します
上記の実行結果からわかるように、各チケットは4回印刷されています。この現象の理由は、4つのスレッドが100チケットを共有していなかったが、それぞれが100チケットを販売したためです。プログラムで4つのチケットウィンドウオブジェクトを作成することは、4つのチケットプログラムを作成することと同じです。各プログラムには100のチケットがあり、各スレッドは独自のリソースを個別に処理しています。例5-4の各スレッドには独自の名前があり、メインスレッドのデフォルト名は「main」、ユーザーが作成した最初のスレッドのデフォルト名は「Thread-0」、2番目のスレッドは「Thread-0」であることに注意してください。 threadデフォルト名は「Thread-1」などです。スレッドの名前を指定する場合は、setName(String name)を呼び出してスレッドの名前を設定できます。

鉄道システムのチケットリソースは実際には共有されているため、上記の運用結果は明らかに不合理です。リソース共有を確実にするために、プログラムで作成できるチケットオブジェクトは1つだけで、複数のスレッドを開いて同じチケットオブジェクトのチケットメソッドを実行できます。簡単に言うと、4つのスレッドが同じチケットプログラムを実行します。時間、あなたはより多くを使用する必要がありますスレッドを実装するための2番目の方法。上記の例を変更し、構築メソッドThread(Runnable target、String name)を使用して、スレッドオブジェクトの作成中にスレッドの名前を指定します。

public class Example05 {
    
    
	public static void main(String[] args) {
    
    
		TicketWindow tw = new TicketWindow(); // 创建TicketWindow实例对象tw
		new Thread(tw, "窗口1").start();      // 创建线程对象并命名为窗口1,开启线程
		new Thread(tw, "窗口2").start();      // 创建线程对象并命名为窗口2,开启线程
		new Thread(tw, "窗口3").start();      // 创建线程对象并命名为窗口3,开启线程
		new Thread(tw, "窗口4").start();      // 创建线程对象并命名为窗口4,开启线程
	}
}
class TicketWindow implements Runnable {
    
    
	private int tickets = 100;

	public void run() {
    
    
		while (true) {
    
    
			if (tickets > 0) {
    
    
				Thread th = Thread.currentThread(); // 获取当前线程
				String th_name = th.getName(); // 获取当前线程的名字
				System.out.println(th_name + " 正在发售第 " + tickets-- + " 张票 ");
			}
		}
	}
}

実行結果:
ここに画像の説明を挿入します
例2では、​​TicketWindowオブジェクトが1つだけ作成され、次に4つのスレッドが作成されます。各スレッドでこのTicketWindowオブジェクトのrun()メソッドが呼び出されるため、4つのスレッドが同じスレッドにアクセスできるようになります。チケット変数、100チケットを共有します。
上記の2つのルーチンから、Runnableインターフェースの実装には、Threadクラスの継承と比較して次の重要な利点があることがわかります。

  1. 同じプログラムコードの複数のスレッドが同じリソースを処理するのに適しており、スレッドをプログラムコードおよびデータから効果的に分離します。これは、オブジェクト指向の設計アイデアをよく反映しています。
  2. Javaの単一継承による制限を回避できます。開発では、特定のクラスを継承したサブクラスを使用してスレッドを作成するという状況に遭遇することがよくあります。クラスは同時に2つの親クラスを持つことができないため、Threadクラスを継承する方法を使用することはできません。 、したがって、Runnableインターフェースを実装する方法のみを採用できます。

実際、ほとんどのアプリケーションは2番目の方法を使用してマルチスレッドを作成します。つまり、Runnableインターフェイスを実装します。

おすすめ

転載: blog.csdn.net/xun08042/article/details/113513714