基本的にJavaアプレットであるProcessingというフレームワークを使用しています。アプレットができるので、重要なイベントを実行する機能があります。ある種の独自のコールバックを親にロールバックすることもできます。私は今それをしていません。おそらくそれが解決策です。今のところ、より POJO ソリューションを探しています。そこで、私の質問を説明するためにいくつかの例を書きました。
コマンド ライン (コンソール) でのキー イベントの使用は無視してください。確かにこれは非常にクリーンなソリューションですが、コマンド ラインでは不可能であり、実際のアプリはコマンド ライン アプリではありません。実際、キーイベントは私にとって良い解決策ですが、キーボード固有の問題だけでなく、イベントとポーリングを理解しようとしています。
これらの例はどちらもブール値を反転します。ブール値が反転したら、一度何かを発射したい。ブール値をオブジェクトにラップして、オブジェクトが変更された場合にイベントを発生させることもできます。不必要に if() ステートメントでポーリングしたくないだけです。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* Example of checking a variable for changes.
* Uses dumb if() and polls continuously.
*/
public class NotAvoidingPolling {
public static void main(String[] args) {
boolean typedA = false;
String input = "";
System.out.println("Type 'a' please.");
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
if (input.equals("a")) {
typedA = true;
} else {
typedA = false;
}
// problem: this is polling.
if (typedA) System.out.println("Typed 'a'.");
}
}
}
これを実行すると、次のように出力されます。
Type 'a' please.
a
Typed 'a'.
一部のフォーラムでは、オブザーバーの使用が提案されました。これにより、監視対象のクラスからイベント ハンドラーが分離されますが、まだ if() が永久ループにあります。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
import java.util.Observer;
/*
* Example of checking a variable for changes.
* This uses an observer to decouple the handler feedback
* out of the main() but still is polling.
*/
public class ObserverStillPolling {
boolean typedA = false;
public static void main(String[] args) {
// this
ObserverStillPolling o = new ObserverStillPolling();
final MyEvent myEvent = new MyEvent(o);
final MyHandler myHandler = new MyHandler();
myEvent.addObserver(myHandler); // subscribe
// watch for event forever
Thread thread = new Thread(myEvent);
thread.start();
System.out.println("Type 'a' please.");
String input = "";
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
// but it's decoupled now because there's no handler here.
if (input.equals("a")) {
o.typedA = true;
}
}
}
}
class MyEvent extends Observable implements Runnable {
// boolean typedA;
ObserverStillPolling o;
public MyEvent(ObserverStillPolling o) {
this.o = o;
}
public void run() {
// watch the main forever
while (true) {
// event fire
if (this.o.typedA) {
setChanged();
// in reality, you'd pass something more useful
notifyObservers("You just typed 'a'.");
// reset
this.o.typedA = false;
}
}
}
}
class MyHandler implements Observer {
public void update(Observable obj, Object arg) {
// handle event
if (arg instanceof String) {
System.out.println("We received:" + (String) arg);
}
}
}
これを実行すると、次のように出力されます。
Type 'a' please.
a
We received:You just typed 'a'.
if() が CPU で NOOP だったとしても問題ありません。しかし、実際にはすべてのパスを比較しています。実際の CPU 負荷が表示されます。これは投票と同じくらい悪いことです。スリープでスロットルを戻すか、最後の更新からの経過時間を比較することはできますが、これはイベント駆動型ではありません。ポーリングが少ないだけです。では、どうすればこれをよりスマートに行うことができますか? ポーリングせずに POJO の変更を監視するにはどうすればよいですか?
C# には、プロパティと呼ばれる興味深いものがあるようです。私は C# の専門家ではないので、これは私が思うほど魔法のようなものではないかもしれません。
private void SendPropertyChanging(string property)
{
if (this.PropertyChanging != null) {
this.PropertyChanging(this, new PropertyChangingEventArgs(property));
}
}