Javaにおけるマルチスレッド実装方式
5552 ワード
Javaにおけるマルチスレッド実装方式
私たちの開発の過程で、よくマルチスレッドの問題に遭遇します.マルチスレッドの実現方式には主に2つあります.Runnableインタフェースを実現し、Threadクラスを統合します.この2つのマルチスレッド実装の方法にもいくつかの違いがある.ネット上ではこの問題について、基本的に切符を買うシステムの例を使っています.次に、コードで次の切符を買うシステムをシミュレートし、2つの切符売り場で10枚の切符を発売し、1つの切符売り場で1つのスレッドを表すことを実現します.
シナリオ1
まず最も簡単な方法から、Thread類を2つ開いて切符を販売します.テストコードは次のとおりです.
テスト結果:Thread-0売票——>10 Thread-1売票——>10 Thread-1売票——>9 Thread-0売票——>9 Thread-1売票——>8 Thread-0売票——>8 Thread-1売票——>7 Thread-0売票——>7 Thread-0売票——>6 Thread-1売票——>6 Thread-0売票——>5 Thread-1売票——>5 Thread-1売票——>4 Thread-0売票——>->4 Thread-1売票——>3 Thread-0売票——>3 Thread-1売票——>2 Thread-0売票——>2 Thread-0売票——>1 Thread-1売票——>1結論:上記のテスト結果から、2つのスレッドはそれぞれ共通の10枚のチケットを売るのではなく、それぞれの10枚のチケットを売っていることがわかり、これは私たちの目標の複数のスレッドが同じリソースを処理することとは大きく異なる.2つの
シナリオ2
リソースオブジェクトを1つしか作成できない以上、
テストコード:
テスト結果:スレッド1チケット販売——>10スレッド1チケット販売——>9スレッド2チケット販売——>8スレッド2チケット販売——>7スレッド2チケット販売——>6スレッド1チケット販売——>5スレッド1チケット販売——>4スレッド2チケット販売——>3スレッド2チケット販売——>2スレッド2チケット販売——>1
結論:この場合,同じリソースを複数のスレッドで処理することを実現した.ここでは,
シナリオ3
テスト結果:スレッド1チケット販売——>10スレッド2チケット販売——>9スレッド2チケット販売——>7スレッド1チケット販売——>8スレッド1チケット販売——>6スレッド2チケット販売——>5スレッド1チケット販売——>4スレッド2チケット販売——>3スレッド2チケット販売——>2スレッド1チケット販売——>1
結論:上記のテストコードでは、2つのスレッドを作成し、各県城は同じ
RunnableとThreadの違いとつながりクラスは親クラスを1つしか継承できません.これは は、Javaの単一継承特性がもたらす限界に比べて は、実際には が
私たちの開発の過程で、よくマルチスレッドの問題に遭遇します.マルチスレッドの実現方式には主に2つあります.Runnableインタフェースを実現し、Threadクラスを統合します.この2つのマルチスレッド実装の方法にもいくつかの違いがある.ネット上ではこの問題について、基本的に切符を買うシステムの例を使っています.次に、コードで次の切符を買うシステムをシミュレートし、2つの切符売り場で10枚の切符を発売し、1つの切符売り場で1つのスレッドを表すことを実現します.
シナリオ1
まず最も簡単な方法から、Thread類を2つ開いて切符を販売します.テストコードは次のとおりです.
public class ticketThread extends Thread {
private int ticket = 10;
public void run() {
for(int i = 0; i < 10; i++){
if(ticket > 0){
try {
sleep(1000);
System.out.println(Thread.currentThread().getName()
+ " ——>" + (ticket--) );
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new ticketThread().start();
new ticketThread().start();
}
}
テスト結果:Thread-0売票——>10 Thread-1売票——>10 Thread-1売票——>9 Thread-0売票——>9 Thread-1売票——>8 Thread-0売票——>8 Thread-1売票——>7 Thread-0売票——>7 Thread-0売票——>6 Thread-1売票——>6 Thread-0売票——>5 Thread-1売票——>5 Thread-1売票——>4 Thread-0売票——>->4 Thread-1売票——>3 Thread-0売票——>3 Thread-1売票——>2 Thread-0売票——>2 Thread-0売票——>1 Thread-1売票——>1結論:上記のテスト結果から、2つのスレッドはそれぞれ共通の10枚のチケットを売るのではなく、それぞれの10枚のチケットを売っていることがわかり、これは私たちの目標の複数のスレッドが同じリソースを処理することとは大きく異なる.2つの
ticketThread
オブジェクトを作成すると、2つのリソースが作成され、各リソースには10枚のチケットがあり、各リソースは独自にそれぞれのリソースを処理しています.したがって、この例では、このチケット販売システムでは、1つのリソースオブジェクトしか作成できませんが、同じリソースオブジェクトを処理するために複数のスレッドを作成し、各スレッドで同じプログラムコードを実行する必要があります.シナリオ2
リソースオブジェクトを1つしか作成できない以上、
ticketThread
を1つだけ作成し、2つの新しいスレッドを追加してチケット販売を実現します.テストコード:
public class ticketThread extends Thread {
private int ticket = 10;
public void run() {
for(int i = 0; i < 10; i++){
synchronized(this){
if(ticket > 0){
try {
sleep(1000);
System.out.println(Thread.currentThread().getName()
+ " ——>" + (this.ticket--) );
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ticketThread t1 = new ticketThread();
new Thread(t1, " 1").start();
new Thread(t1, " 2").start();
}
}
テスト結果:スレッド1チケット販売——>10スレッド1チケット販売——>9スレッド2チケット販売——>8スレッド2チケット販売——>7スレッド2チケット販売——>6スレッド1チケット販売——>5スレッド1チケット販売——>4スレッド2チケット販売——>3スレッド2チケット販売——>2スレッド2チケット販売——>1
結論:この場合,同じリソースを複数のスレッドで処理することを実現した.ここでは,
Thread(ThreadGroup groupOb, String threadName)
を用いてticketThread
をパラメータとして新しく作成したスレッドに伝達する新しいスレッドを作成した.この場合、新しく作成された2つのスレッドは、ticketThread
のrun()
メソッドを実行し、2つのスレッドが同じリソースを処理することを実現する.しかし、原理的には、この案は案3と同じである.シナリオ3
Runnable
を使用してマルチスレッドを実装する.テストコード:public class ticketThread implements Runnable {
private int ticket = 10;
public void run() {
for(int i = 0; i < 10; i++){
// synchronized(this){
if(ticket > 0){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()
+ " ——>" + (ticket--) );
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
// }
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ticketThread t1 = new ticketThread();
new Thread(t1, " 1").start();
new Thread(t1, " 2").start();
}
}
テスト結果:スレッド1チケット販売——>10スレッド2チケット販売——>9スレッド2チケット販売——>7スレッド1チケット販売——>8スレッド1チケット販売——>6スレッド2チケット販売——>5スレッド1チケット販売——>4スレッド2チケット販売——>3スレッド2チケット販売——>2スレッド1チケット販売——>1
結論:上記のテストコードでは、2つのスレッドを作成し、各県城は同じ
ticketThread
オブジェクトのrun()
メソッドを呼び出し、同じオブジェクトの変数(ticket)
のインスタンスにアクセスし、このプログラムは私たちのニーズを完璧に満たしています.RunnableとThreadの違いとつながり
Thread
を使用する限界です.Runnable
はインタフェースです.このインタフェースを実現すればいいです.従って、実際の開発プロセスでは、Runnable
インタフェースによって実現され、Runnable
はリソース共有の実現により適している.Runnable
を使用することができ、Javaの単一継承特性がもたらす限界により、ある疲れたサブクラスを継承してマルチスレッドに入れる場合、1つのクラスが同時に2つの親クラスを持つことができないため、Threadクラスを継承する方法が使用できない場合、このクラスはRunnableインタフェースしか採用できない方法である.Thread
もRunnbale
インターフェースのサブクラスである.public class Thread extends Object implements Runnable
Runnable
オブジェクトを使用する場合、Runnable
で定義されたサブクラスにはstart()
メソッドはなく、Thread
クラスにのみ存在し、Thread
クラスを観察すると、public Thread(Runnable target)
のサブクラスインスタンスを受け入れる構造メソッドRunanble
があり、つまりThread
クラスを起動してRunnable
マルチスレッドを実現することができる.