では、キューに入れるけど、一定時間経過してからしか処理したい。または、連打された場合、最後の処理だけ実行したい。みたいなことがあると思います。
こういう時に、BlockingQueue<E>を使います。BlockingQueueはインタフェースです。そのため、その実装であるjava.util.concurrent.DelayQueue<E>を使います。
でも、addできるのは、java.util.concurrent.Delayedをインプリメントしたクラスだけ。
実装した例は以下のような感じ。
public static void main(String[] args) throws InterruptedException {
long[] waits = { 10, 8, 6, 0, 1, 2 };
String[] tests = { "10", "8", "6", "0", "1", "2" };
// 遅延時間のばらばらのデータをqueueに入れる
BlockingQueue<Task> queue = new DelayQueue<Task>();
for (int i = 0; i < waits.length; i++) {
queue.add(new Task(tests[i], waits[i]));
}
// 空になるまでループする。
while (!queue.isEmpty()) {
Task task = queue.take();
task.execute();
}
}
/**
* java.util.concurrent.Delayedを実装した例.
*
*/
static class Task implements Delayed {
final private long execTime;
final private String text;
/**
* テキストと遅延時間を指定したコンストラクタ.
*
* @param text
* @param wait
*/
Task(String text, long wait) {
this.text = text;
this.execTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(wait);
}
/*
* (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(Delayed o) {
long diff = execTime - ((Task) o).execTime;
if (diff == 0) {
return 0;
}
return (diff > 0) ? 1 : -1;
}
/*
* (non-Javadoc)
*
* @see
* java.util.concurrent.Delayed#getDelay(java.util.concurrent.TimeUnit)
*/
@Override
public long getDelay(TimeUnit unit) {
// 残遅延時間を返却
System.out.println(String.format("%tT getDelay text=[%s] w=[%d]",
new Date(), text, execTime - System.nanoTime()));
return execTime - System.nanoTime();
}
/**
* 処理.
*/
public void execute() {
System.out.println(String.format("%tT execute text=[%s]秒後",
new Date(), text));
}
}
long[] waits = { 10, 8, 6, 0, 1, 2 };
String[] tests = { "10", "8", "6", "0", "1", "2" };
// 遅延時間のばらばらのデータをqueueに入れる
BlockingQueue<Task> queue = new DelayQueue<Task>();
for (int i = 0; i < waits.length; i++) {
queue.add(new Task(tests[i], waits[i]));
}
// 空になるまでループする。
while (!queue.isEmpty()) {
Task task = queue.take();
task.execute();
}
}
/**
* java.util.concurrent.Delayedを実装した例.
*
*/
static class Task implements Delayed {
final private long execTime;
final private String text;
/**
* テキストと遅延時間を指定したコンストラクタ.
*
* @param text
* @param wait
*/
Task(String text, long wait) {
this.text = text;
this.execTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(wait);
}
/*
* (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(Delayed o) {
long diff = execTime - ((Task) o).execTime;
if (diff == 0) {
return 0;
}
return (diff > 0) ? 1 : -1;
}
/*
* (non-Javadoc)
*
* @see
* java.util.concurrent.Delayed#getDelay(java.util.concurrent.TimeUnit)
*/
@Override
public long getDelay(TimeUnit unit) {
// 残遅延時間を返却
System.out.println(String.format("%tT getDelay text=[%s] w=[%d]",
new Date(), text, execTime - System.nanoTime()));
return execTime - System.nanoTime();
}
/**
* 処理.
*/
public void execute() {
System.out.println(String.format("%tT execute text=[%s]秒後",
new Date(), text));
}
}
■実行結果
00:51:24 getDelay text=[0] w=[-910031]
00:51:24 execute text=[0]秒後
00:51:24 getDelay text=[1] w=[892204037]
00:51:25 getDelay text=[1] w=[-1095530]
00:51:25 execute text=[1]秒後
00:51:25 getDelay text=[2] w=[998366343]
00:51:26 getDelay text=[2] w=[-1155035]
00:51:26 execute text=[2]秒後
00:51:26 getDelay text=[6] w=[3995886907]
00:51:30 getDelay text=[6] w=[-13674573]
00:51:30 execute text=[6]秒後
00:51:30 getDelay text=[8] w=[1985765928]
00:51:32 getDelay text=[8] w=[-11499437]
00:51:32 execute text=[8]秒後
00:51:32 getDelay text=[10] w=[1986226602]
00:51:34 getDelay text=[10] w=[-11083182]
00:51:34 execute text=[10]秒後
Queueに登録する順は関係ありませんが、キューの処理順は、compareTo()メソッドの戻り順で処理されます。そのため、遅延時間によって処理順を決めています。 「execute」とログが出ている行を追っかけていくと、指定した通りの時間で処理されていますね。 ログをそこだけに絞り込むと、以下のようになります。遅延指定した時間に実行されています。
00:51:24 execute text=[0]秒後
00:51:25 execute text=[1]秒後
00:51:26 execute text=[2]秒後
00:51:30 execute text=[6]秒後
00:51:32 execute text=[8]秒後
00:51:34 execute text=[10]秒後
0 件のコメント:
コメントを投稿