2009-03-30 4 views
2

私はJava/Hibernate/Spring/Quartzで動作するゲームサーバーを持っています。ゲーム時計はクォーツタイマーで刻々と変化しますが、うまくいきます。指定された間隔で任意のコードを呼び出すための洗練された方法が必要です

しかし、私は特定の調整可能な間隔で(ゲーム時間ではなくリアルタイムで)発生する必要がある多くのことがあります。

たとえば、24時間のゲーム時間(サーバーのクロック乗数に応じてリアルタイムから約47分まで)ごとに、一度のゲームアクションが毎回行われます。たとえば、補給や何がありますか。

現在のシステムはかなり粗いですが、動作します - データベースには本質的にcronのテーブルがあります - 文字列キー、次のイベントの実行時間、そして時、分、秒、日その次のものタイム・ティッカーはそれをチェックし、そのコード(イベント・ストリング・キー)を含むメッセージをキューに送り、現在の時刻に日、分、秒を加え、次の実行時刻として設定します。

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

私はこれがうまくいくことを理解していますが、本当にうまく座りません。あなた自身の小さなクラスにそれぞれのコードを入れるために、あなたの解決策は何でしょうか?これをカバーするデザインパターンは何ですか? (私はそこに1つあると確信しています)。私はいくつかのアイデアを持っていますが、いくつかの意見を聞きたいと思います。

答えて

0

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

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(); 
    } 
} 

を、あなただけのクラスパスにJARファイルをドロップすることで、新たな振る舞いを追加するには、Java 6のServiceLoaderのようなものを使用することができます。

+0

私はこれを答えとしてマークしていません。なぜなら、それは簡単な答えではありません - 確かに、マッピングはスイッチより優れていますが、それは本当にエレガントではありません。 ServiceLoaderはより優れたアプローチですが、Springのような既に実装されている他のインフラストラクチャには対応していません。 –

0

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

まず、時間の縮尺はです。この時間の壁時計時間との関係が一定である限り、私は、私はちょうど私が使用しているはずだ

DateTime getFutureTime(VirtualTimeSpan timespan) 

のような署名を持っているであろうと、単一のクラスにこのスケーリングの振る舞いを委譲したいかなり確信しています仮想時間スパンをリアルタイムのインスタンスにマップします。その後、リアルタイムで操作することができます。これにより、標準スケジューリング機能を使用することができるため、多少の単純化が可能になります。

2番目の部分は、将来のワーカープロセスのスケジューリング作業に関するものです。これにはいくつかのコアテクノロジーがあります。概念的には、JMSは、これらの多くのJava-Grand-Dadだと思います。使用しているものと同じような概念と、必要なものを定義しています。興味深いコンセプトを見るにはJMSを見てください。セレクタを使用して、特定のワーカーにタスクを送信します。

悲しいかな、JMSはほとんどの人にとって法案には当てはまりませんでした。多くの人々は、それがあまりにも重量すぎるか、実装があまりにもバグであることを発見しました。だから、通常、人々は自宅で作られた待ち行列技術で終わった。しかし、そのコンセプトはすべてそこにあります。石英を使うことはできませんか?

1

Command Patternの亜種を使用します。私はIIntervalCommandクラスを作るためにCommandパターンを拡張します。これにはintervalプロパティと、Executeメソッドに加えてreadonly CanExecuteプロパティがあります。

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

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

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

大文字小文字の区別は避けてください。オブジェクトをインスタンス化するときにデータベースを削除し、パラメータを設定することができます。または、それを保持し、すべてのIIntervalCommandsを作成するファクトリの一部として使用します。

1

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

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

Javaコードは、イベントのあなたの持続キューを失うことなく、イベントを処理する再起動することができますこの方法:

のようなものを持っていることは可能なはずです。

http://en.wikipedia.org/wiki/Priority_queue'>あなたがまだ持っていない場合、プライオリティキューは価値があります。

関連する問題