Thread クラスの拡張クラスを作る:
1. Thread クラスの拡張クラスを作る
2. そのクラスの run メソッドを宣言する
3. そのクラスのインスタンスを作る
4. start メソッドを呼び出す
CountTenA.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class CountTenA extends Thread{
public static void main(String[] args){
CountTenA ct = new CountTenA();
ct.start();
for(int i = 0; i < 10; i++){
System.out.println("main:i = " + i);
}
}
public void run(){
for(int i = 0; i < 10; i++){
System.out.println("run:i = " + i);
}
}
}
|
CountTenA.java の実行結果は:
[wtopia koji]$ java CountTenA
main:i = 0
main:i = 1
main:i = 2
main:i = 3
main:i = 4
main:i = 5
main:i = 6
main:i = 7
main:i = 8
main:i = 9
run:i = 0
run:i = 1
run:i = 2
run:i = 3
run:i = 4
run:i = 5
run:i = 6
run:i = 7
run:i = 8
run:i = 9
Runnable インターフェースを実装したクラスを作る:
1. Runnable インターフェースを実装したクラスを作る.
2. run メソッドを実装する.
3. そのクラスのインスタンスを作り, Thread オブジェクトを生成する.
4. Thread オブジェクトの start メソッドを呼び出す.
CountTenB.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class CountTenB implements Runnable{
public static void main(String[] args){
CountTenB ct = new CountTenB();
Thread th = new Thread(ct);
th.start();
for(int i = 0; i < 10; i++){
System.out.println("main:i = " + i);
}
}
public void run(){
for(int i = 0; i < 10; i++){
System.out.println("run:i = " + i);
}
}
}
|
CountTenB.java の実行結果は:
[wtopia koji]$ java CountTenB
main:i = 0
main:i = 1
main:i = 2
main:i = 3
main:i = 4
main:i = 5
main:i = 6
main:i = 7
main:i = 8
main:i = 9
run:i = 0
run:i = 1
run:i = 2
run:i = 3
run:i = 4
run:i = 5
run:i = 6
run:i = 7
run:i = 8
run:i = 9
方法 A 方法 B
用途: 簡単なクラス向け 複雑なクラス向け
スーパークラス: Thread クラス 何でもよい
クラス宣言: Thread クラスの拡張 Runnable インターフェースの実装
スレッドの起動: start メソッド Thread 経由で start を起動
実行開始点: run メソッド run メソッド
矛盾が発生している.
BadBank.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class BadBank{
private int value = 0;
public void addMoney(int money){
int currentValue = value;
System.out.println(Thread.currentThread() + "が addMoney に入った.");
value += money;
if(currentValue + money != value){
System.out.println(Thread.currentThread() + "で矛盾が発生した.");
System.exit(-1);
}
System.out.println(Thread.currentThread() + "が addMoney から出た.");
}
}
|
BadBankTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class BadBankTest extends Thread{
BadBank bank;
public BadBankTest(BadBank bank){
this.bank = bank;
}
public void run(){
while(true){
bank.addMoney(100);
bank.addMoney(-100);
}
}
public static void main(String[] args){
BadBank bank = new BadBank(); // BadBank を生成
new BadBankTest(bank).start();
new BadBankTest(bank).start();
}
}
|
BadBank.java と BadBankTest.java の実行結果は:
[wtopia koji]$ javac BadBank.java BadBankTest.java
[wtopia koji]$ java BadBankTest
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
... (省略)
Thread[Thread-1,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]で矛盾が発生した.
Thread[Thread-1,5,main]が addMoney に入った.
Thread[Thread-1,5,main]で矛盾が発生した.
GoodBank.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class GoodBank{
private int value = 0;
public synchronized void addMoney(int money){
int currentValue = value;
System.out.println(Thread.currentThread() + "が addMoney に入った.");
value += money;
if(currentValue + money != value){
System.out.println(Thread.currentThread() + "で矛盾が発生した.");
System.exit(-1);
}
System.out.println(Thread.currentThread() + "が addMoney から出た.");
}
}
|
GoodBankTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class GoodBankTest extends Thread{
GoodBank bank;
public GoodBankTest(GoodBank bank){
this.bank = bank;
}
public void run(){
while(true){
bank.addMoney(100);
bank.addMoney(-100);
}
}
public static void main(String[] args){
GoodBank bank = new GoodBank(); // GoodBank を生成
new GoodBankTest(bank).start();
new GoodBankTest(bank).start();
}
}
|
GoodBank.java と GoodBankTest.java の実行結果は:
[wtopia koji]$ javac GoodBank.java GoodBankTest.java
[wtopia koji]$ java GoodBankTest
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
Thread[Thread-0,5,main]が addMoney に入った.
Thread[Thread-0,5,main]が addMoney から出た.
... (省略)
... (永遠に繰り返していいく)
class Runner extends Thread{
private boolean running = true;
public void stopRunning(){
running = faluse;
}
public void run(){
while(running){
doSomething();
}
}
}
Periodic.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class Periodic{
public static void main(String[] args){
for(int i = 0; i < 10; i++){
int tm = i * 1000;
System.out.println("Start sleep:tm = " + tm);
try{
Thread.sleep(tm);
}catch(InterruptedException e){
//
}
}
}
}
|
Periodic.java の実行結果は:
[wtopia koji]$ java Periodic
Start sleep:tm = 0
Start sleep:tm = 1000
Start sleep:tm = 2000
Start sleep:tm = 3000
Start sleep:tm = 4000
Start sleep:tm = 5000
Start sleep:tm = 6000
Start sleep:tm = 7000
Start sleep:tm = 8000
Start sleep:tm = 9000
JoinTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class JoinTest extends Thread{
public static void main(String[] args){
JoinTest th = new JoinTest();
System.out.println("main:はじめ");
System.out.println("main:終了待ちに入る");
th.start();
try{
th.join();
}catch(InterruptedException e){
System.out.println(e);
}
System.out.println("main:終わり");
}
public void run(){
System.out.println("run:スレッド実行開始");
try{
Thread.sleep(5000);
}catch(InterruptedException e){
System.out.println(e);
}
System.out.println("run:スレッド実行終了");
}
}
|
JoinTest.java の実行結果は:
[wtopia koji]$ java JoinTest
main:はじめ
main:終了待ちに入る
run:スレッド実行開始
run:スレッド実行終了
main:終わり
ProducerConsumer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | public class ProducerConsumer{
public static void main(String[] args){
MyQueue queue = new MyQueue(3);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
producer.start();
consumer.start();
}
}
class MyQueue{
int[] intbuf;
int start;
int count;
public MyQueue(int size){
intbuf = new int[size];
start = 0;
count = 0;
}
public synchronized void put(int n) throws InterruptedException{
while(count >= intbuf.length){
System.out.println(Thread.currentThread().getName() + " wait: バッファの空きを待つ");
wait();
}
int end = (start + count) % intbuf.length;
intbuf[end] = n;
count++;
notifyAll();
}
public synchronized int take() throws InterruptedException{
while(count == 0){
System.out.println(Thread.currentThread().getName() + " wait: データを待つ");
wait();
}
int n = intbuf[start];
start = (start + 1) % intbuf.length;
count--;
notifyAll();
return n;
}
}
class Producer extends Thread{
static final int END = -1;
MyQueue queue = null;
Producer(MyQueue queue){
this.queue = queue;
}
public void run(){
try{
for(int i = 0; i < 100; i++){
int n = produce(i);
queue.put(n);
}
queue.put(Producer.END);
}catch(InterruptedException e){
}
}
int produce(int n){
sleepRandomly();
System.out.println("Producer: " + getName() + "は " + n + " を生産完了");
return n;
}
void sleepRandomly(){
try{
int n = (int)(Math.random() * 1000);
Thread.sleep(n);
}catch(InterruptedException e){
}
}
}
class Consumer extends Thread{
MyQueue queue = null;
Consumer(MyQueue queue){
this.queue = queue;
}
public void run(){
try{
while(true){
int n = queue.take();
if(n == Producer.END){
break;
}
consume(n);
}
}catch(InterruptedException e){
//
}
}
void consume(int n){
System.out.println("Consumer: " + getName() + "は " + n + " を消費中");
sleepRandomly();
}
void sleepRandomly(){
try{
int n = (int)(Math.random() * 1000);
Thread.sleep(n);
}catch(InterruptedException e){
//
}
}
}
|
ProducerConsumer.java の実行結果は:
[wtopia koji]$ java ProducerConsumer
Thread-1 wait: データを待つ
Producer: Thread-0は 0 を生産完了
Consumer: Thread-1は 0 を消費中
Producer: Thread-0は 1 を生産完了
Producer: Thread-0は 2 を生産完了
Producer: Thread-0は 3 を生産完了
Consumer: Thread-1は 1 を消費中
Consumer: Thread-1は 2 を消費中
Consumer: Thread-1は 3 を消費中
Producer: Thread-0は 4 を生産完了
Consumer: Thread-1は 4 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 5 を生産完了
Consumer: Thread-1は 5 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 6 を生産完了
Consumer: Thread-1は 6 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 7 を生産完了
Consumer: Thread-1は 7 を消費中
Producer: Thread-0は 8 を生産完了
Producer: Thread-0は 9 を生産完了
Consumer: Thread-1は 8 を消費中
Producer: Thread-0は 10 を生産完了
Consumer: Thread-1は 9 を消費中
Consumer: Thread-1は 10 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 11 を生産完了
Consumer: Thread-1は 11 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 12 を生産完了
Consumer: Thread-1は 12 を消費中
Producer: Thread-0は 13 を生産完了
Consumer: Thread-1は 13 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 14 を生産完了
Consumer: Thread-1は 14 を消費中
Producer: Thread-0は 15 を生産完了
Consumer: Thread-1は 15 を消費中
Producer: Thread-0は 16 を生産完了
Consumer: Thread-1は 16 を消費中
Producer: Thread-0は 17 を生産完了
Consumer: Thread-1は 17 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 18 を生産完了
Consumer: Thread-1は 18 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 19 を生産完了
Consumer: Thread-1は 19 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 20 を生産完了
Consumer: Thread-1は 20 を消費中
Thread-1 wait: データを待つ
Producer: Thread-0は 21 を生産完了