[セットトップ]最近蓄積されたjavaの詳細


ここ数日ずっとマルチスレッドの問題を研究しています.これはずっと弱点なので、これまでずっと心を込めて勉強していませんでした.ここ数日、ネット上でいくつかの資料を見て、利益が得られたような気がします.ここで記録してください.
昨日静態類の合併問題について見て、卵が痛いのを見始めました.拭いて、静態類の中に合併問題があるはずがありません.設計に問題があるでしょう.静態類でグローバル変数を処理して、抽選を探します@.そこで卵が痛くて実験して、ははは、とても面白いです!間違いがあれば、指摘を歓迎します.ありがとうございます.
コードは次のとおりです.
まず、時間依存計算用のツールクラスです.
public final class TimeUtil {
    /*             calendar  , static        (         ,        )   ,      ! */
    private static Calendar calendar = Calendar.getInstance();

    /**
     *                  
     * @param date
     * @return dayOfYear
     */
    public static int getDay(Date date) {
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_YEAR);
    }

    /**
     *             
     * @param date
     * @return month     -1
     */
    public static int getMonth(Date date) {
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

    /**
     *              
     * @param str    yyyy-MM-dd hh:mm:ss
     * @return
     */
    public static Date getTimeByStr(String str) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date time = null;
        try {
            time = df.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return time;
    }

次にテストスレッドクラス
public class TestStaticThread implements Runnable {

    String timeStr;

    public TestStaticThread(String timeStr) {
            this.timeStr = timeStr;
    }

    @Override
    public void run() {
        try {
            //  sleep        !
            Thread.sleep(100L);

            Date time = TimeUtil.getTimeByStr(timeStr);
            int day = TimeUtil.getDay(time);
            int month = TimeUtil.getMonth(time);

            System.out.println("  [" + Thread.currentThread().getName() + "]     [" + timeStr + "], " +
                    "        ,       [" + day + "],       [" + (month + 1) + " ]");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

最後はプログラムの入口
public class StaticTest {
    public static void main(String[] args) {
        TestStaticThread testStaticThread1 = new TestStaticThread("2013-02-05 15:15:15");
        TestStaticThread testStaticThread2 = new TestStaticThread("2013-04-10 18:45:30");
        TestStaticThread testStaticThread3 = new TestStaticThread("2013-06-15 18:45:30");
        Thread t1 = new Thread(testStaticThread1, "t1");
        Thread t2 = new Thread(testStaticThread2, "t2");
        Thread t3 = new Thread(testStaticThread3, "t3");

        t1.start();
        t2.start();
        t3.start();
    }
}

明らかに、上のgetDay()とgetMonth()に問題があります!何?信じないと言ったのか?結果に問題を説明させましょう!
  [t2]     [2013-04-10 18:45:30],         ,       [36],       [2 ]
  [t1]     [2013-02-05 15:15:15],         ,       [36],       [2 ]
  [t3]     [2013-06-15 18:45:30],         ,       [166],       [6 ]

Process finished with exit code 0

はははは、断固として间违って木があります!!
では、修正するのは簡単で、2つの方法があります.
1、getDay()とgetMonth()を同期方法に設定し、以下のように変更する
public static synchronized int getDay(Date date)
public static synchronized int getMonth(Date date)

2、上記のcalendarをメソッド内に入れる、すなわち以下のようにする
 
  
 
public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_YEAR);
    }
public static synchronized int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

しかし、1つ目の方法は実際には問題があり、静的ロックがこのClassであり、Objectをロックするわけではないため、プログラムが他の場所でTimeUtile tu=new TimeUtil()でオブジェクトをインスタンス化し、1つのスレッドがgetDay()を呼び出し(TimeUtil.getDay()を呼び出し、もう1つのスレッドがgetMonth()を呼び出す(tu.getMonth()ここではgetMonth()を非静的方法に変更する必要がある.静的な方法であれば安全です!)実はやはり問題が発生します!もちろん、このクラスの構造方法を書き直し、インスタンス化を禁止して安全を保証することができます.
メソッド2の弊害は、このツールクラスにメソッドが多い場合、毎回Calendar calendar=Calendar.getInstance();,少し問題があるかもしれませんが、メモリと関係があるので、静的メソッドのGCでオブジェクトを回収するメカニズムが非静的メソッドのオブジェクトを回収するメカニズムと同じかどうかはまだよく分かりませんので、結論を出すのはよくありません.夜、自分でプログラムを書いてみてください.
もう一つの小さな知識点は、マルチスレッドについて、wait()メソッドが呼び出されると、スレッドはすぐにロックを解除しますが、notifyAll()は、ロックリソースを待ってブロックされている他のスレッドを呼び覚ますだけで、現在所有しているロックを解放しません.この点は非常に重要です.
また、溶岩のブログに感謝して、多くの新しい姿勢を学びました.次は彼のマルチスレッドに関する特集リンクです.
クリックしてリンクを開く