2009年6月15日月曜日

Java スレッドの一時停止、再開、終了

スレッドの終了方法


runメソッドを終了すると、そのスレッドは解放されなくなります。
ですのでrunメソッドを停止するフラグ変数を用意して、その変数を変更することによって、runメソッドが終了するようにします。

class MyThread extends Thread {
boolean end = false;

public void run() {
while(!end){
//end変数がfalseの間処理を繰り返す。
}
}
}


スレッドの休止方法


スレッドを一時停止するにはwaitメソッドを使用します。
※wait、notify、notifyAllはsynchronized指定がされたメソッド・ブロックでのみ使用できます。

スレッドの再開方法


一時停止したスレッドを再開するにはnotifyメソッドを使用します。
※wait、notify、notifyAllはsynchronized指定がされたメソッド・ブロックでのみ使用できます。

synchrnonizedメソッド・synchrnonized構文


synchronized 修飾されたメソッド/ブロックは、1つのスレッドからしか実行されません。他のスレッドがアクセスしようとすると先に実行しているスレッドの処理が終了するまで待機します。
つまり、複数のスレッドが同じ変数にアクセスすると不整合が発生する可能性がありますが、synchronized 修飾されたメソッド/ブロックはマルチスレッドによる同時アクセスを行わない為、不整合の発生を防ぐことができます。

synchronized 修飾されたメソッド
メソッドの処理を行っている間、そのメソッドに外部からアクセスできないようにします。


synchronized 構文
ブロック内の処理を行っている間、引数に指定したインスタンスに外部からアクセスできないようにします。
synchronized(ブロックするインスタンス){
//実行する処理
}




以下のサンプルはRunボタンでスレッドを開始し、Waitボタンでスレッドの一時停止/再開、Endボタンでスレッドを終了します。
package multiThreadSample;

import java.awt.Button;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ThreadSample03 extends Frame implements ActionListener{

private static final long serialVersionUID = 1L;

public static void main(String[] args){
new ThreadSample03();
}

Label lbl1;
Button btnRun1;
Button btnWait1;
Button btnEnd1;

MyThread3 t1 = null;

public ThreadSample03(){ 
this.setTitle("ThreadSample01");
this.setSize(300,300);
this.setLayout(new GridLayout(2,1));

lbl1 = new Label();
this.add(lbl1);
Panel p1 = new Panel();
btnRun1 = new Button("Run");
btnRun1.addActionListener(this);
btnWait1 = new Button("Wait");
btnWait1.addActionListener(this);
btnEnd1 = new Button("End");
btnEnd1.addActionListener(this);
p1.add(btnRun1);
p1.add(btnWait1);
p1.add(btnEnd1);
this.add(p1);

this.setVisible(true);
}

public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnRun1){
t1 = new MyThread3(lbl1,500);
t1.start();
}else if (e.getSource() == btnWait1){
t1.setStop();
}else if (e.getSource() == btnEnd1){
t1.stopRun();
}
} 
}

class MyThread3 extends Thread {
boolean end = false; 
boolean stop = false;
Label lbl;
int time;  


public MyThread3(Label lbl, int time){
this.lbl = lbl;
this.time = time;   
}

public void run() {
int i = 0;
while(!end){
lbl.setText("Count:" + i);
i++;
try {
Thread.sleep(time);
synchronized(this){
if (stop) wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void stopRun(){
stop = true;
}

public synchronized void setStop() {
stop = !stop;
if (!stop) {
notify();
}

}


}

0 件のコメント: