2

OK、Java/Hibernate/Spring/Quartz でゲーム サーバーを実行しています。ゲーム クロックはクォーツ タイマーで時を刻み、問題なく動作します。

ただし、特定の微調整可能な間隔で (リアルタイムではなくゲーム時間で) 発生する必要があることが他にもたくさんあります。

たとえば、24 時間のゲーム時間 (サーバーのクロック乗数に応じて、リアルタイムで約 47 分) ごとに、補給などの 1 日 1 回のさまざまなゲーム アクションが発生します。

さて、現在のシステムはかなり荒削りですが、うまくいきます - 私は基本的にcronであるテーブルをデータベースに持っています - 文字列キー、次のイベントの実行時間、そしてその後の次のイベントまでの時間、分、秒、そして日. タイム ティッカーはそれをチェックし、そのコード (イベント文字列キー) を含むメッセージをキューに送信し、現在の時刻に日、分、秒を追加し、それを次の実行時刻として設定します。

メッセージ リスナーはグロディな部分です。キーをオンにして、そのメソッドの 1 つをヒットします。

これで問題なく機能することがわかりましたが、実際にはうまくいきません。コードの各部分を独自の小さなクラスに含めるには、これに対する解決策は何ですか? これをカバーする設計パターンは何ですか?(確かにあると思います)。いろいろ考えはありますが、意見をお聞きしたいです。

4

5 に答える 5

1

キーをオンにする代わりに、ハッシュテーブルを使用してこれらのイベントをディスパッチできます。このように、タイマー イベントはお互いを知る必要がありません。

次のようなものがある可能性があります。

timerQueue.registerHandler("key",new TimerHandler(){
   // do something timer related  
});

このようにして、永続化されたイベント キューを失うことなく、イベントを処理する Java コードを再開できます。

http://en.wikipedia.org/wiki/Priority_queue'>プライオリティ キューをまだお持ちでない場合は、検討する価値があります。

于 2009-03-30T20:59:04.423 に答える
1

コードのセットを切り替えるのではなく、コードをマップへのキーとして使用できます。値はハンドラー インターフェイスを実装するオブジェクトです。これにより、新しいイベント タイプをより柔軟に追加できます。

パターンは次のようになります。

private final Map<String, Handler> handlers = new TreeMap<String, Handler>();

public void register(String event, Handler handler) { 
  handlers.put(event, handler); 
}

public void handle(String event) {
  Handler handler = handler.get(event);
  if (handler == null) {
    /* Log or throw an exception for unknown event type. */
  }
  else {
    handler.execute();
  }
}

ハンドラーを明示的に登録するのではなく、ServiceLoaderJAR をクラスパスにドロップするだけで、Java 6 のようなものを使用して新しい動作を追加できます。

于 2009-03-30T18:30:35.420 に答える
1

のバリアントを使用しCommand Patternます。Command パターンを拡張して、IIntervalCommand クラスを作成します。Execute メソッドに加えて、interval プロパティと読み取り専用の CanExecute プロパティがあります。

次に、IIntervalCommands のリストを保持する CommandList クラスを作成します。現在のゲーム時間を渡す CheckToExecute というメソッドがあります。CheckToExecute メソッドは、コマンドごとに CanExecute を呼び出してリストを走査します。経過時間が発生した場合、CanExecute は true を返します。CanExecute が true を返す場合、CheckToExecute は IIntervalCommand を実装するオブジェクトの Execute メソッドを呼び出します。

その後、追加のゲーム イベントを追加するには、IIntervalClass を実装する新しいクラスを作成します。オブジェクトをインスタンス化し、IntervalCommandList に追加します。

イベントの処理に時間がかかる場合、コマンドは処理を別のスレッドとして生成できます。間隔が再び経過した場合でも、スレッドが戻るまで、CanExecute プロパティに false を返します。または、間隔が再び経過した場合は、別のスレッドから生成します。

巨大なケースステートメントを避けます。オブジェクトをインスタンス化するときに、データベースを削除してパラメータを設定できます。または、それを保持して、すべての IIntervalCommands を作成するファクトリの一部として使用します。

于 2009-03-30T19:22:09.523 に答える
0

概念的には、あなたは2つのことをしていると思います。

まず、時間のスケーリングされたバージョンがあります。この時間と実時間の関係が一定である限り、このスケーリング動作を単一のクラスに委任するだけで、次のようなシグネチャを持つと確信しています。

DateTime getFutureTime( VirtualTimeSpan timespan)

これを使用して、仮想タイムスパンをリアルタイムのインスタンスにマッピングします。その後、リアルタイムで操作できます。これにより、標準のスケジューリング機能を使用できるため、作業が少し簡単になります。

2番目の部分は、将来のワーカープロセスの作業のスケジューリングに関するものです。これを使用するコアテクノロジーは多数あります。概念的には、 JMSはこれらの多くのjava-grand-dadであると思います。これは、使用しているものや必要なものとよく似た概念を定義します。JMSを見ると、興味深いと思われる概念を確認するのに適していると思います。JMSは、セレクターを使用して、あなたが宣言したものと同じように、特定のワーカーにタスクを送信します。

残念ながら、JMSはほとんどの人にとって法案に適合しているようには見えませんでした。多くの人が、それが重すぎるか、実装がバグが多すぎることに気づきました。そのため、通常、人々は自家製のキューテクノロジーを使用することになりました。しかし、概念はすべてそこにあります。クォーツだけでは使えませんか?

于 2009-03-30T18:37:59.147 に答える
0

私は個人的にこれをデータベースに入れず、別のサービスをバックグラウンドで実行し続けます。次に、Web サービスまたは Web アプリケーションは、プロセス間通信を介してこのサービスと通信します。ただし、これが Java の世界にどのように変換されるかはわかりません。

于 2009-03-30T18:13:58.253 に答える