Thread and Runnableの違い
Thread is theプロセス,Runnable is theプロセスオブジェクト[最初に明らかにする必要がある問題]
プログラムとプロセスの違いのように、マルチスレッドプログラミングを把握するには、まず、スレッドオブジェクトとスレッドの違いを明らかにする必要があります.
スレッドオブジェクトは、スレッドを生成できるオブジェクトです.たとえばjavaプラットフォームのThreadオブジェクト、Runnableオブジェクトです.スレッドとは、実行中のポインティングシーケンスを指します.Javaプラットフォームでは、runメソッドボディの相対的に独立したプロセスを実行するスレッドオブジェクトのstart()から開始します.
著者のレベルに鑑みて,それらの定義をより正確な語彙で記述することはできない.しかし、この2つの本質的な違いのある概念は初心者によく体得してもらい、紹介の深さとルーチン分析の増加に伴い、それらが代表する本当の意味が徐々に理解されます.
天下の難事は必ず易から始まり、天下の大事は必ず細から始まる.
まず、最も簡単な「単一スレッド」から始めましょう.(1)引用符で説明するのは相対的な単一スレッドであり、(2)javaに基づいています.
Javaファイルのコンパイルに成功したら、コマンドラインに入力します.
java BeginClass
今何があったの?Javaプログラマー一人一人が、彼がjavaを勉強し始めた最初の分からこの質問に触れています.
問題ですが、いったい何が起こっているのか知っていますか.
JVMプロセスが開始され、同じJVMプロセスにおいて、1つのプロセスのみが存在し、それ自体である.そしてこのJVM環境では,すべてのプログラムの実行がスレッドで実行される.JVMは、指定されたプログラムのエントリポイントを実行するプライマリスレッドを最初に生成します.このプログラムでは,メインスレッドがmainメソッドから実行される.mainメソッドが終了すると、メインスレッドの実行が完了します.JVMプロセスも終了します.
メインスレッドがmainメソッドを実行しているのを見て、プログラムロジックを実行するプロセスは1つのスレッドだけです.
これは単一スレッドです.これはJVMが提供する単一スレッド環境です.実際、JVMの下部には少なくともこのようなバックグラウンドスレッドやjava以外のスレッドがゴミ回収されていますが、これらのスレッドは私たちにとってアクセスできません.単一スレッドだと思っています.
メインスレッドはJVM自身が起動し、ここではスレッドオブジェクトから生成されません.このスレッドではmainメソッドという命令シーケンスを実行します.理解していますが、これ以上研究できる内容はありません.
[接触マルチスレッド]
このプログラムを実行するとmainメソッドの最初の行にスレッドオブジェクトが生成されますが、スレッド起動はありません.
mainメソッドの2行目にスレッドオブジェクトが生成され、スレッドが開始されます.
mainメソッドの3行目で、1つのスレッドを生成して起動した後、メインスレッド自身も他の文を実行し続けます.
まずThreadオブジェクトの具体的な内容を研究しないで、上の2つの概念、スレッドオブジェクトとスレッドを少し思い出してみましょう.JAVAでは、スレッドオブジェクトはJVMによって生成される一般的なObjectサブクラスです.スレッドは、CPUがこのオブジェクトに割り当てる実行プロセスです.このスレッドが何をしているのかは、スレッドオブジェクトが何をしているのかではなく、この実行プロセスが何をしているのかということです.すぐに分からないと思ったら、焦らないでください.しかし、それらが同じことではないことを覚えておいてください.
ここではJAVAにおけるスレッドオブジェクトの考察を開始する.
JAVAでは、1スレッドを開始するには、2つの方法があります.1つはThreadインスタンスを直接呼び出すstart()メソッドであり、2つはRunableインスタンスをThreadインスタンスに渡して呼び出すstart()メソッドである.
前述したように、スレッドオブジェクトとスレッドはまったく異なる概念です.ここでは、スレッドが起動したわけではないスレッドのインスタンスを生成します.一方、起動スレッドとは、あるスレッドオブジェクト上でインスタンスに対応するスレッドが起動し、スレッドが終了するとすぐに消えることはありません.
多くの本から見られる基礎知識については言うまでもありません.基礎知識である以上、普通の文書では読めない内容にも重点を置いています.そこで、このセクションでは、2つのスレッドオブジェクトがスレッドを生成する方法の違いに重点を置きます.
MyThreadのインスタンスを生成し、start()メソッドを呼び出すと、このインスタンスに対応するスレッドが生成されます.
言うまでもなく、最終的には0から99まで印刷されます.今、私たちは少し模様を游びました.
言うまでもなく、基礎編(一)では、単一CPUのために101を印刷し、0から99を印刷するのが一般的であることが知られています.しかし、スレッドを制御して、私たちの意思通りに実行することができます.
では、mtインスタンスに対応するスレッドをやっと見ました(もし私がmtスレッドを責めないでくださいと言ったら、私はできるだけそう言わないでください).実行が完了すると、メインスレッドは印刷101される.mtスレッドの実行が終了するまで、現在のスレッド(ここではメインスレッド)を待たせるからです.「スレッドオブジェクトaにjoin()を呼び出す方法は、現在実行中のスレッドがスレッドオブジェクトaに対応するスレッドの実行が完了してから実行を継続するのを待つことです.」 この言葉をよく理解して覚えておいてください.私がここでこの知識点を引き出した目的は、次の例を見続けるためです.
スレッドオブジェクトmtの実行が完了したら、メインスレッドを休ませ、再びこのスレッドオブジェクト上でスレッドを開始します.結果として、
Exception in thread "main" java.lang.IllegalThreadStateException
つまり,このスレッドオブジェクトは一時的に1回実行が完了すると,二度と実行できなくなる.具体的な実装を見てみましょう.
Threadのインスタンスがstart()メソッドを呼び出すと、このインスタンスのstartedタグはtrueとしてマークされます.実際には、このスレッドが後で実行されるかどうかにかかわらず、start()を1回呼び出すと実行する機会がなくなります.これは、次のことを意味します.
[Threadインスタンスのstart()により、1つのThreadインスタンスに1つのスレッドしか生成できない]
では、1つのインスタンスで複数のスレッド(つまり、私たちがよく言うスレッドプール)を生成するには、どうすればいいのでしょうか.これがRunnableインタフェースが私たちに与えた偉大な機能です.
名前の通り、Runnableのインスタンスは実行可能ですが、それ自体は直接実行できません.Threadオブジェクトにパッケージされて実行する必要があります.
もちろんこの結果はmt.start()と変わらない.しかし、RunnableインスタンスをThreadオブジェクトに複数回パッケージすると、実際に同じインスタンスでスレッドを開始していることがわかります.
xはインスタンスオブジェクトであるが、結果としてxが999に加算され、この10スレッドが同じrオブジェクト上で実行されていることを示す.なお,この例は単一CPU上で動作するため,複数のスレッドが同時に動作する共通のオブジェクトを同期していない.ここでは、説明の便宜上、同期を簡素化しますが、実際の環境ではプログラムがどの環境で実行されるか予知できないので、同期を考慮する必要があります.
ここでは、スレッドの生成方法の違いによって生成されるスレッドの違いを説明する完全な例を示します.
上の10個のスレッドオブジェクトが生成した10個のスレッド実行時に1を10回印刷しました.次の10スレッドオブジェクトで生成された10スレッドの実行時に1~10を印刷します.以下の10個のスレッドを同じインスタンス(Runnableインスタンス)の複数のスレッドと呼ぶ.
転載先:http://www.blogjava.net/sunxiaobo/archive/2008/02/28/182788.html
プログラムとプロセスの違いのように、マルチスレッドプログラミングを把握するには、まず、スレッドオブジェクトとスレッドの違いを明らかにする必要があります.
スレッドオブジェクトは、スレッドを生成できるオブジェクトです.たとえばjavaプラットフォームのThreadオブジェクト、Runnableオブジェクトです.スレッドとは、実行中のポインティングシーケンスを指します.Javaプラットフォームでは、runメソッドボディの相対的に独立したプロセスを実行するスレッドオブジェクトのstart()から開始します.
著者のレベルに鑑みて,それらの定義をより正確な語彙で記述することはできない.しかし、この2つの本質的な違いのある概念は初心者によく体得してもらい、紹介の深さとルーチン分析の増加に伴い、それらが代表する本当の意味が徐々に理解されます.
天下の難事は必ず易から始まり、天下の大事は必ず細から始まる.
まず、最も簡単な「単一スレッド」から始めましょう.(1)引用符で説明するのは相対的な単一スレッドであり、(2)javaに基づいています.
class BeginClass{
public static void main(String[] args){
for(int i=0;i<100;i++)
System.out.println("Hello,World!");
}
}
Javaファイルのコンパイルに成功したら、コマンドラインに入力します.
java BeginClass
今何があったの?Javaプログラマー一人一人が、彼がjavaを勉強し始めた最初の分からこの質問に触れています.
問題ですが、いったい何が起こっているのか知っていますか.
JVMプロセスが開始され、同じJVMプロセスにおいて、1つのプロセスのみが存在し、それ自体である.そしてこのJVM環境では,すべてのプログラムの実行がスレッドで実行される.JVMは、指定されたプログラムのエントリポイントを実行するプライマリスレッドを最初に生成します.このプログラムでは,メインスレッドがmainメソッドから実行される.mainメソッドが終了すると、メインスレッドの実行が完了します.JVMプロセスも終了します.
メインスレッドがmainメソッドを実行しているのを見て、プログラムロジックを実行するプロセスは1つのスレッドだけです.
これは単一スレッドです.これはJVMが提供する単一スレッド環境です.実際、JVMの下部には少なくともこのようなバックグラウンドスレッドやjava以外のスレッドがゴミ回収されていますが、これらのスレッドは私たちにとってアクセスできません.単一スレッドだと思っています.
メインスレッドはJVM自身が起動し、ここではスレッドオブジェクトから生成されません.このスレッドではmainメソッドという命令シーケンスを実行します.理解していますが、これ以上研究できる内容はありません.
[接触マルチスレッド]
class MyThread extends Thread{
public void run(){
System.out.println("Thread say:Hello,World!");
}
}
public class MoreThreads{
public static void main(String[] args){
new MyThread();
new MyThread().start();
System.out.println("Main say:Hello,World");
}
}
このプログラムを実行するとmainメソッドの最初の行にスレッドオブジェクトが生成されますが、スレッド起動はありません.
mainメソッドの2行目にスレッドオブジェクトが生成され、スレッドが開始されます.
mainメソッドの3行目で、1つのスレッドを生成して起動した後、メインスレッド自身も他の文を実行し続けます.
まずThreadオブジェクトの具体的な内容を研究しないで、上の2つの概念、スレッドオブジェクトとスレッドを少し思い出してみましょう.JAVAでは、スレッドオブジェクトはJVMによって生成される一般的なObjectサブクラスです.スレッドは、CPUがこのオブジェクトに割り当てる実行プロセスです.このスレッドが何をしているのかは、スレッドオブジェクトが何をしているのかではなく、この実行プロセスが何をしているのかということです.すぐに分からないと思ったら、焦らないでください.しかし、それらが同じことではないことを覚えておいてください.
ここではJAVAにおけるスレッドオブジェクトの考察を開始する.
JAVAでは、1スレッドを開始するには、2つの方法があります.1つはThreadインスタンスを直接呼び出すstart()メソッドであり、2つはRunableインスタンスをThreadインスタンスに渡して呼び出すstart()メソッドである.
前述したように、スレッドオブジェクトとスレッドはまったく異なる概念です.ここでは、スレッドが起動したわけではないスレッドのインスタンスを生成します.一方、起動スレッドとは、あるスレッドオブジェクト上でインスタンスに対応するスレッドが起動し、スレッドが終了するとすぐに消えることはありません.
多くの本から見られる基礎知識については言うまでもありません.基礎知識である以上、普通の文書では読めない内容にも重点を置いています.そこで、このセクションでは、2つのスレッドオブジェクトがスレッドを生成する方法の違いに重点を置きます.
class MyThread extends Thread{
public int x = 0;
public void run(){
for(int i=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(x++);
}
}
}
MyThreadのインスタンスを生成し、start()メソッドを呼び出すと、このインスタンスに対応するスレッドが生成されます.
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
}
}
言うまでもなく、最終的には0から99まで印刷されます.今、私たちは少し模様を游びました.
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
System.out.println(101);
}
}
言うまでもなく、基礎編(一)では、単一CPUのために101を印刷し、0から99を印刷するのが一般的であることが知られています.しかし、スレッドを制御して、私たちの意思通りに実行することができます.
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
mt.join();
System.out.println(101);
}
}
では、mtインスタンスに対応するスレッドをやっと見ました(もし私がmtスレッドを責めないでくださいと言ったら、私はできるだけそう言わないでください).実行が完了すると、メインスレッドは印刷101される.mtスレッドの実行が終了するまで、現在のスレッド(ここではメインスレッド)を待たせるからです.「スレッドオブジェクトaにjoin()を呼び出す方法は、現在実行中のスレッドがスレッドオブジェクトaに対応するスレッドの実行が完了してから実行を継続するのを待つことです.」 この言葉をよく理解して覚えておいてください.私がここでこの知識点を引き出した目的は、次の例を見続けるためです.
public class Test {
public static void main(String[] args) throws Exception{
MyThread mt = new MyThread();
mt.start();
mt.join();
Thread.sleep(3000);
mt.start();
}
}
スレッドオブジェクトmtの実行が完了したら、メインスレッドを休ませ、再びこのスレッドオブジェクト上でスレッドを開始します.結果として、
Exception in thread "main" java.lang.IllegalThreadStateException
つまり,このスレッドオブジェクトは一時的に1回実行が完了すると,二度と実行できなくなる.具体的な実装を見てみましょう.
public synchronized void start() {
if (started)
throw new IllegalThreadStateException();
started = true;
group.add(this);
start0();
}
Threadのインスタンスがstart()メソッドを呼び出すと、このインスタンスのstartedタグはtrueとしてマークされます.実際には、このスレッドが後で実行されるかどうかにかかわらず、start()を1回呼び出すと実行する機会がなくなります.これは、次のことを意味します.
[Threadインスタンスのstart()により、1つのThreadインスタンスに1つのスレッドしか生成できない]
では、1つのインスタンスで複数のスレッド(つまり、私たちがよく言うスレッドプール)を生成するには、どうすればいいのでしょうか.これがRunnableインタフェースが私たちに与えた偉大な機能です.
class R implements Runnable{
private int x = 0;
public void run(){
for(int i=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(x++);
}
}
}
名前の通り、Runnableのインスタンスは実行可能ですが、それ自体は直接実行できません.Threadオブジェクトにパッケージされて実行する必要があります.
public class Test {
public static void main(String[] args) throws Exception{
new Thread(new R()).start();
}
}
もちろんこの結果はmt.start()と変わらない.しかし、RunnableインスタンスをThreadオブジェクトに複数回パッケージすると、実際に同じインスタンスでスレッドを開始していることがわかります.
public class Test {
public static void main(String[] args) throws Exception{
R r = new R();
for(int i=0;i<10;i++)
new Thread(r).start();
}
}
xはインスタンスオブジェクトであるが、結果としてxが999に加算され、この10スレッドが同じrオブジェクト上で実行されていることを示す.なお,この例は単一CPU上で動作するため,複数のスレッドが同時に動作する共通のオブジェクトを同期していない.ここでは、説明の便宜上、同期を簡素化しますが、実際の環境ではプログラムがどの環境で実行されるか予知できないので、同期を考慮する必要があります.
ここでは、スレッドの生成方法の違いによって生成されるスレッドの違いを説明する完全な例を示します.
package debug;
import java.io.*;
import java.lang.Thread;
class MyThread extends Thread{
public int x = 0;
public void run(){
System.out.println(++x);
}
}
class R implements Runnable{
private int x = 0;
public void run(){
System.out.println(++x);
}
}
public class Test {
public static void main(String[] args) throws Exception{
for(int i=0;i<10;i++){
Thread t = new MyThread();
t.start();
}
Thread.sleep(10000);//
R r = new R();
for(int i=0;i<10;i++){
Thread t = new Thread(r);
t.start();
}
}
}
上の10個のスレッドオブジェクトが生成した10個のスレッド実行時に1を10回印刷しました.次の10スレッドオブジェクトで生成された10スレッドの実行時に1~10を印刷します.以下の10個のスレッドを同じインスタンス(Runnableインスタンス)の複数のスレッドと呼ぶ.
転載先:http://www.blogjava.net/sunxiaobo/archive/2008/02/28/182788.html