1

日付/時刻を UTC 数値形式 (変更されたユリウス日番号) で格納する多くのテーブルを含むデータベースがあります。

これはうまく機能しますが、もちろん、日付をユーザーに表示する必要がある場合は、日付/時刻を UTC 数値形式からローカライズされた文字列形式に変換する必要があります。JDK カレンダー API は歴史的に正確な夏時間とタイム ゾーン オフセットを提供するため、私はこれだけのためにグレゴリオ暦を使用してきました。タイムスタンプを UTC から現地時間にマップするためだけに使用します。

この変換を実行する必要があるテーブルが非常に多くあり、Calendar オブジェクトの作成にはコストがかかるため、ロケールのタイム ゾーンが変更された場合にのみ、新しい GregorianCalendar オブジェクトを作成しています。現在のカレンダーを JulianDay クラスの静的メンバー フィールドに保持しています (これは、UTC をローカル マッピングに提供するために使用する関数を提供するクラスです)。JulianDay のフィールドは次のとおりです。

public final class JulianDay {

    private static final int YEAR = 0;
    private static final int MONTH = 1;
    private static final int DAY = 2;
    private static final int HOURS = 3;
    private static final int MINUTES = 4;
    private static final int SECONDS = 5;
    private static final int MILLIS = 6;

    public  static final double POSIX_EPOCH_MJD = 40587.0;
    private static final String TIME_ZONE_UTC   = "UTC";
    private static final GregorianCalendar CAL_UTC = 
            new GregorianCalendar(TimeZone.getTimeZone(TIME_ZONE_UTC));

    private static GregorianCalendar c_selCal = null;

    public static void setCurrentCalendar(String tzid) 
            { JulianDay.c_selCal = JulianDay.findCalendarForTimeZone(tzid); }

    public static GregorianCalendar getCurrentCalendar() 
            { return JulianDay.c_selCal; }
    :
    :
}

上記はシングルスレッドのクライアント側 GUI アプリケーションですが、この API の大部分を使用するサーバー側 Web アプリケーションをすぐに開発する必要があります。JDK Calendar API への投資を維持し、何らかの方法でアプリケーション スレッドを安全に保つ方法を見つける必要があります。Joda 時間はオプションですが、可能であれば、その依存関係を追加したくありません (Java API を使用するのは、タイム ゾーン データベースへのイージーモード アクセスだけです)。

Calendar は明らかにスレッドに敵対的であるため、ここからどうすればよいか正確にはわかりません。

私の考えでは、JulianDay クラスは GregorianCalendar のすべてのインスタンスを (タイム ゾーン ID 文字列から) 構築するため、コードをリファクタリングしてgetCurrentCalendar()、カレンダーの参照を発行するメソッドを削除できると考えています。

GregorianCalendarへのすべてのアクセスを内に限定できればJulianDay、たとえそれが危険なほど変更可能なクラスであっても、私のアプリケーションはスレッドセーフであると安全に仮定できますか? クラス内であっても、へのアクセスをGregorianCalendarロック オブジェクトと同期する必要があります。よろしいですか?JulianDay

4

3 に答える 3

1

可変インスタンスは、適切に同期されていれば、スレッドセーフにすることができます。不変インスタンスの利点は、同期する必要がないことだけです。そうです、すべての変化する変更をカレンダーに同期すれば、カレンダーを使い続けることができます。

しかし!サーバー側アプリは、マルチスレッド クライアント アプリとはまったく異なります。単一の同期ポイントは、アプリをブロックする確実な方法です。負荷によっては、接続が停止する可能性があります。ThreadLocal は同期の問題を軽減する可能性がありますが、各 Calendar は 1 つのスレッド内でのみ表示されるため、スレッドの再利用について考えてください。

典型的なアプリ サーバー環境では、連続するユーザーだけでなく、同じセッション内でも同じスレッドが再利用されます。ユニットが終了すると、同じスレッドが別のユーザーのために別の作業ユニットを取得できます。したがって、カレンダーが変更可能で、特定のユーザーに応じて変更する必要がある場合、必要になるたびにカレンダーを設定する必要があります。したがって、実質的にキャッシュ効果はまったくありません。

アプリサーバー環境でのそのようなサービス(日付を変換するサービス)には(数年前に行っていたので「あった」と言います)ステートレスBeanとステートフルBeanがありましたが、今ではキャッシュサービスの方が適切だと思います、タイムゾーンごとにいくつかのインスタンスで満たされています。

インスタンスが変更可能である限り、キャッシュ内でロックする必要があります (おそらく削除して再挿入する必要があります)。また、キャッシュは適切なサイズで管理する必要があります。

Joda のように、常にステートレスのままでいることをお勧めします。また、レコードごとに新しいオブジェクトを動的に作成することを控えるために (規模によっては、アプリ サーバーを遅くする別の方法で) 事前に入力されたキャッシュを使用します。

于 2013-06-07T07:52:17.113 に答える