swingを使って画面から、スレッドを起動して、終了したら、画面で値を表示といった使い方を想定しています。
2014/06/21
concurrent
CountDownLatch
FutureTask
java
Thread
Javaです。concurrentです。
swingを使って画面から、スレッドを起動して、終了したら、画面で値を表示といった使い方を想定しています。
SwingWorkerから、ExecutorServiceを使うというようなことを試してみました。
あと、スレッドもひとつではなく複数を想定しています。
ためしたコードでは、3つです。
参考
ExecutorService での処理のキャンセル方法 - Java 入門
今回いろいろ試してみました。
CountDownLatch
ExecutorService
FutureTask
swingを使って画面から、スレッドを起動して、終了したら、画面で値を表示といった使い方を想定しています。
SwingWorkerから、ExecutorServiceを使うというようなことを試してみました。
あと、スレッドもひとつではなく複数を想定しています。
ためしたコードでは、3つです。
参考
ExecutorService での処理のキャンセル方法 - Java 入門
今回いろいろ試してみました。
CountDownLatch
ExecutorService
FutureTask
package concurrent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class TestMain4 {
public static void main(String[] args) throws InterruptedException {
a();
}
public static class Dummy {
public void open() {
};
public void close() {
};
}
public static class MySwingWorker extends SwingWorker<Object, Object> {
final int numThread = 3;
// 明示的な shutdown が行われるまでは、スレッドはプール内に存在します。
ExecutorService executor = Executors.newFixedThreadPool(numThread);
CountDownLatch countDownLatch = new CountDownLatch(numThread);
final List<FutureTask<String>> list = new ArrayList<>();
@Override
protected Object doInBackground() throws Exception {
// 実行するタスクを作成
for (int i = 0; i < numThread; i++) {
list.add(new FutureTask<>(
new MyCallable("" + i, countDownLatch), "" + i));
}
// タスクの実行
for (FutureTask<String> ft : list) {
executor.submit(ft);
}
System.out.println("*** 1 this line" + new Date());
// 以前に送信されたタスクが実行されますが、新規タスクは受け入れられません。
executor.shutdown();
System.out.println("*** 2 this line" + new Date());
// 待ち
countDownLatch.await();
return "OK";
}
/**
* この実装はよいのか?
*/
public void cancel() {
super.cancel(true);
// 後処理
executor.shutdownNow();
for (FutureTask<String> task : list) {
// 全てのタスクにキャンセルを投げる
// スレッドが停止?
task.cancel(true);
}
}
}
static class MyCallable implements Runnable {
String name;
CountDownLatch countDownLatch;
public MyCallable(String name, CountDownLatch countDownLatch) {
this.name = name;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
Dummy dummy = null;
try {
dummy = new Dummy();
dummy.open();
System.out.printf("*** start %s %s %n", name, new Date());
/* ループ処理をイメージ */
for (int i = 0; i < 1; i++) {
for (int j = 0; j < 1000000000; j++) {
// キャンセルされた場合よばれるはず...
if (Thread.interrupted()) {
throw new InterruptedException("!!cancelled!!");
}
}
}
System.out.println("*** 計算終了");
} catch (Exception e) {
// e.printStackTrace();
// キャンセルするとここを通る
System.err.println(e.getLocalizedMessage());
} finally {
// 後処理
if (dummy != null)
dummy.close();
// 必ず呼ばれて欲しい
countDownLatch.countDown();
System.out.printf("*** end %s %s %n", name, new Date());
}
}
}
static void a() throws InterruptedException {
final MySwingWorker worker = new MySwingWorker();
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt);
if (!SwingWorker.StateValue.DONE.equals(worker.getState()))
return;
for (FutureTask<String> task : worker.list) {
try {
if (task.isDone() && !task.isCancelled())
System.out.println("result:" + task.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
});
SwingUtilities.invokeLater(worker);
Thread.sleep(10);
// キャンセルする場合は
// worker.cancel();
}
}
: