マルチスレッド
| 日本語 | 多筋道 |
| 英語 | multithread |
| ふりがな | まるちすれっど |
| フリガナ | マルチスレッド |
スレッドが複数ある状態のこと。
スレッド、つまりプログラムの流れを複数作り、別々の処理を行うことを「マルチスレッド」という。
マルチスレッドを利用することで、たとえばあるスレッドはウィンドウのユーザーインターフェイス処理、もうひとつのスレッドはバックグラウンドの画像処理、のように別々の処理を平行して行うことができる。
うまく使うことでユーザーの不満を減らすことができるが、複雑になりやすいため使用が難しい機能でもある。
特に、フィールドのアクセスには注意が必要。ローカル変数はメソッドを呼び出すたびに作られるため競合しないが、フィールドは共通のものを使用できるため、場合によっては同期を取り排他処理を行う必要がある。ただし、排他処理も複雑化するとデッドロックのバグを生む可能性がある。
いずれにせよ、複雑化すればするほど泥沼に陥りやすい機能のため、できるだけシンプルに使うことを心がけた方がいいだろう。
スレッド、つまりプログラムの流れを複数作り、別々の処理を行うことを「マルチスレッド」という。
マルチスレッドを利用することで、たとえばあるスレッドはウィンドウのユーザーインターフェイス処理、もうひとつのスレッドはバックグラウンドの画像処理、のように別々の処理を平行して行うことができる。
うまく使うことでユーザーの不満を減らすことができるが、複雑になりやすいため使用が難しい機能でもある。
特に、フィールドのアクセスには注意が必要。ローカル変数はメソッドを呼び出すたびに作られるため競合しないが、フィールドは共通のものを使用できるため、場合によっては同期を取り排他処理を行う必要がある。ただし、排他処理も複雑化するとデッドロックのバグを生む可能性がある。
いずれにせよ、複雑化すればするほど泥沼に陥りやすい機能のため、できるだけシンプルに使うことを心がけた方がいいだろう。
参考サイト
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// ↓最初に作られたスレッド(スレッドA)の流れ。
System.out.println( 1 );
System.out.println( 2 );
System.out.println( 3 );
// ↓と、実行されていきます。
// 1
// 2
// 3
OtherThread thread = new OtherThread();
// もうひとつスレッド(スレッドB)を作ります。
thread.start();
// これで、スレッドが2つになって「マルチスレッド」に
// なりました。
// スレッドAからtwoRunner()メソッドを呼び出します。
twoRunner( "スレッドA" );
// スレッドA : 1
// スレッドB : 1
// スレッドA : 2
// スレッドB : 2
// スレッドA : 3
// スレッドA : 終了
// スレッドB : 3
// スレッドB : 終了
// スレッド全部が終了するまで
// 終了しません。なので、スレッドAが
// 先に終わっても、スレッドBの方が
// 中断されることはありません。
}
/**
* スレッドAとスレッドBの両方から呼び出されます。
*/
public static void twoRunner( String name )
{
try
{
// カウンター。
int counter = 0;
// ローカル変数はスレッドで共有されることは
// ありません。再帰呼び出しを考えれば
// 当然ですが。
System.out.println( name + " : " + ++counter );
// スレッドを5秒止めます。
Thread.sleep( 5 * 1000 );
System.out.println( name + " : " + ++counter );
// スレッドAを5秒止めます。
Thread.sleep( 5 * 1000 );
System.out.println( name + " : " + ++counter );
System.out.println( name + " : 終了" );
}
catch( InterruptedException e )
{
// sleep()メソッドが途中で中断されると
// InterruptedException例外が投げられます。
// 滅多にないですが。
e.printStackTrace();
}
}
}
/**
* 別スレッドとして実行するためのクラス。
*/
class OtherThread extends Thread
{
/**
* Threadクラスのrun()メソッドを
* オーバーライドしたメソッド。このメソッドが
* 別スレッドとして呼び出されます。
*/
public void run()
{
try
{
// 最初に2秒待ちます。
sleep( 2 * 1000 );
// SampleクラスのtwoRunner()メソッドを呼び出します。
Sample.twoRunner( "スレッドB" );
}
catch( InterruptedException e )
{
// sleep()メソッドが途中で中断されると
// InterruptedException例外が投げられます。
// 滅多にないですが。
e.printStackTrace();
}
}
}
public class Sample
{
public static void main( String[] args )
{
// ↓最初に作られたスレッド(スレッドA)の流れ。
System.out.println( 1 );
System.out.println( 2 );
System.out.println( 3 );
// ↓と、実行されていきます。
// 1
// 2
// 3
OtherThread thread = new OtherThread();
// もうひとつスレッド(スレッドB)を作ります。
thread.start();
// これで、スレッドが2つになって「マルチスレッド」に
// なりました。
// スレッドAからtwoRunner()メソッドを呼び出します。
twoRunner( "スレッドA" );
// スレッドA : 1
// スレッドB : 1
// スレッドA : 2
// スレッドB : 2
// スレッドA : 3
// スレッドA : 終了
// スレッドB : 3
// スレッドB : 終了
// スレッド全部が終了するまで
// 終了しません。なので、スレッドAが
// 先に終わっても、スレッドBの方が
// 中断されることはありません。
}
/**
* スレッドAとスレッドBの両方から呼び出されます。
*/
public static void twoRunner( String name )
{
try
{
// カウンター。
int counter = 0;
// ローカル変数はスレッドで共有されることは
// ありません。再帰呼び出しを考えれば
// 当然ですが。
System.out.println( name + " : " + ++counter );
// スレッドを5秒止めます。
Thread.sleep( 5 * 1000 );
System.out.println( name + " : " + ++counter );
// スレッドAを5秒止めます。
Thread.sleep( 5 * 1000 );
System.out.println( name + " : " + ++counter );
System.out.println( name + " : 終了" );
}
catch( InterruptedException e )
{
// sleep()メソッドが途中で中断されると
// InterruptedException例外が投げられます。
// 滅多にないですが。
e.printStackTrace();
}
}
}
/**
* 別スレッドとして実行するためのクラス。
*/
class OtherThread extends Thread
{
/**
* Threadクラスのrun()メソッドを
* オーバーライドしたメソッド。このメソッドが
* 別スレッドとして呼び出されます。
*/
public void run()
{
try
{
// 最初に2秒待ちます。
sleep( 2 * 1000 );
// SampleクラスのtwoRunner()メソッドを呼び出します。
Sample.twoRunner( "スレッドB" );
}
catch( InterruptedException e )
{
// sleep()メソッドが途中で中断されると
// InterruptedException例外が投げられます。
// 滅多にないですが。
e.printStackTrace();
}
}
}
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// ↓最初に作られたスレッド(スレッドA)の流れ。
System.out.println( 1 );
System.out.println( 2 );
System.out.println( 3 );
// ↓と、実行されていきます。
// 1
// 2
// 3
OtherThread thread = new OtherThread();
// もうひとつスレッド(スレッドB)を作ります。
thread.start();
// これで、スレッドが2つになって「マルチスレッド」に
// なりました。
// スレッドAからtwoRunner()メソッドを呼び出します。
twoRunner( "スレッドA" );
// スレッドA : 1
// スレッドB : 1
// スレッドA : 2
// スレッドB : 2
// スレッドA : 3
// スレッドA : 終了
// スレッドB : 3
// スレッドB : 終了
// スレッド全部が終了するまで
// 終了しません。なので、スレッドAが
// 先に終わっても、スレッドBの方が
// 中断されることはありません。
}
/**
* スレッドAとスレッドBの両方から呼び出されます。
*/
public static void twoRunner( String name )
{
try
{
// カウンター。
int counter = 0;
// ローカル変数はスレッドで共有されることは
// ありません。再帰呼び出しを考えれば
// 当然ですが。
System.out.println( name + " : " + ++counter );
// スレッドを5秒止めます。
Thread.sleep( 5 * 1000 );
System.out.println( name + " : " + ++counter );
// スレッドAを5秒止めます。
Thread.sleep( 5 * 1000 );
System.out.println( name + " : " + ++counter );
System.out.println( name + " : 終了" );
}
catch( InterruptedException e )
{
// sleep()メソッドが途中で中断されると
// InterruptedException例外が投げられます。
// 滅多にないですが。
e.printStackTrace();
}
}
}
/**
* 別スレッドとして実行するためのクラス。
*/
class OtherThread extends Thread
{
/**
* Threadクラスのrun()メソッドを
* オーバーライドしたメソッド。このメソッドが
* 別スレッドとして呼び出されます。
*/
public void run()
{
try
{
// 最初に2秒待ちます。
sleep( 2 * 1000 );
// SampleクラスのtwoRunner()メソッドを呼び出します。
Sample.twoRunner( "スレッドB" );
}
catch( InterruptedException e )
{
// sleep()メソッドが途中で中断されると
// InterruptedException例外が投げられます。
// 滅多にないですが。
e.printStackTrace();
}
}
}




