8-1. Thread
Thread の基礎
Java で並列にプロセスを動かすには、 java.lang.Thread クラスを継承し
ます。
そして、 void run()
メソッドをオーバライドします。
プロセスを起動するときは、クラスのインスタンスに対して、
start()
メソッドを呼び出すと、オーバライドしたメソッドが並列に起動されます。
起動したプロセスを終了するまで待つには join()
メソッ
ドを呼び出すと、終了するまで待たされます。
例8-1
git://edu.net.c.dendai.ac.jp/git/spro/8/1
Thread1.java
public class Thread1 extends Thread {
private static int serial=0;
private int num;
public Thread1() {
num=serial++;
}
@Override
public String toString() {
return "Thread"+num;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interruputed");
}
System.out.println(this);
}
}
Main.java
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class Main {
private static final int n = 10;
public static void main(String[] args) {
@SuppressWarnings("unchecked")
Supplier<String>[] testList = new Supplier[]{
()->testRun(),
()->testStart(),
()->testJoin(),
};
long prev,now;
prev=System.currentTimeMillis();
for(Supplier<String> test : testList) {
System.out.println(test.get());
now = System.currentTimeMillis();
System.out.println(now-prev);
prev=now;
}
}
private static List<Thread> getTList() {
List<Thread> tlist = new ArrayList<>();
for(int i=0; i<n; i++) {
tlist.add(new Thread1());
}
return tlist;
}
private static String testRun() {
List<Thread> tlist = getTList();
for(Thread t : tlist) {
t.run();
}
return "TestRun finished.";
}
private static String testStart() {
List<Thread> tlist = getTList();
for(Thread t : tlist) {
t.start();
}
return "TestStart finished.";
}
private static String testJoin() {
List<Thread> tlist = getTList();
for(Thread t : tlist) {
t.start();
}
for(Thread t : tlist) {
try {
t.join();
} catch (InterruptedException e) {
}
}
return "TestJoin finished.";
}
}
Interrupted
起動しているプロセスを途中で止めるには、いくつか非推奨のメソッドが ありますが、それらを使わずに、 interrupt メソッドの呼び出しで行い ます。
interrupt メソッドでは、オブジェクトの状態を変え、
super.interrupt()
を呼び出して終えるようにします。
super.interrupt メソッドにより、Thread クラスに InterruptedException が発生します。 これにより、実行中の sleep, join, wait メソッドが中断し、例外処理 を行います。
処理を中断する際、終了処理を確実に実施して終了するようにするのが肝 要です。
ThreadGroup
Thread の集まりをコントロールするために、java.lang.ThreadGroup が あります。 ThreadGroup のインスタンスを予め作成しておき、Thread を作成すると きに、Thread のコンストラクタに ThreadGroup のインスタンスを
例8-2
git://edu.net.c.dendai.ac.jp/git/spro/8/2
Thread2.java
public class Thread2 extends Thread {
private static int serial=0;
private int num;
private long dulation;
public Thread2(long dulation, ThreadGroup sg, String str) {
super(sg,str);
this.dulation = dulation;
num=serial++;
}
@Override
public String toString() {
return "Thread"+num;
}
@Override
public void interrupt() {
super.interrupt();
}
@Override
public void run() {
try {
Thread.sleep(dulation);
} catch (InterruptedException e) {
System.out.println(this+" is Interruputed");
}
System.out.println(this+" is finished");
}
}
Main.java
import java.util.Scanner;
public class Main {
private static final int n = 10;
private static long dulation = 20000;
public static void main(String[] args) {
ThreadGroup sg = new ThreadGroup("");
System.out.println("start");
for(int i=0; i<n; i++) {
new Thread2(dulation,sg,"").start();
}
Scanner sc = new Scanner(System.in);
sc.nextLine();
sc.close();
sg.interrupt();
}
}
8-2. 演習
演習8-1
以下のプログラムで、配列の一部分の合計を求めるクラス Thread3 を作 成しなさい。
git://edu.net.c.dendai.ac.jp/git/spro/8/3
Main.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
final private static int n=10000000;
final private static int k=10;
public static void main(String[] args) throws InterruptedException {
double[] a = getRandom(n);
long[] t = new long[3];
double[] result = new double[2];
t[0] = System.currentTimeMillis();
List<Thread3> tlist = new ArrayList<>();
for(int i=0; i<k; i++) {
Thread3 thread = new Thread3(a,i*n/k,(i+1)*n/k-1);
thread.start();
tlist.add(thread);
}
result[0]=0;
for(Thread3 thread : tlist) {
thread.join();
result[0] += thread.getValue();
}
t[1] = System.currentTimeMillis();
result[1]=Arrays.stream(a).sum();
t[2] = System.currentTimeMillis();
for(int i = 0; i < 2; i++) {
System.out.println(result[i]);
System.out.println(t[i+1] - t[i]);
}
}
private static double[] getRandom(int n2) {
double[] result = new double[n2];
for(int i=0; i<n2; i++ ) {
result[i] = Math.random();
}
return result;
}
}