0

ログオブジェクトを追加するキューが存在するシングルトンクラスによって非同期スレッドを実装しました。しかし、 java.util.linkedlist.remove でそのような要素の例外を与えていません

public class LogDaoSingleton extends Thread {

private static LogDaoSingleton logDaoSingleton = new LogDaoSingleton();

private static Queue<ScoreLoggingObject> queue = new LinkedList<ScoreLoggingObject>();

private static Boolean firstTime = true;


private LogDAO logDAO;
private SkipLogDaoImpl skipLogDAO;

Connection conNull = null;
Connection connection = null;

private int counter = 0;

Connection con = null;

Connection skipCon = null;

public static LogDaoSingleton getInstance() {
    return logDaoSingleton;
}

private static void createInstance() {
    logDaoSingleton = new LogDaoSingleton();
}

private LogDaoSingleton() {
    try {
        con = HMDBUtil.getNonTxNullProdConnection();
        conNull = HMDBUtil.getNonTxNullProdConnection();
        skipCon = HMDBUtil.getNonTxNullProdConnection();
        logDAO = new LogDAOImpl();
        skipLogDAO = new SkipLogDaoImpl();
        hmCandScoreLog = PropertyReader.getStringProperty(
                CacheConstants.CLUSTER_REPORT,
                CacheConstants.HM_CAND_SCORE_LOG);
        hmCandScoreLogNull = PropertyReader.getStringProperty(
                CacheConstants.CLUSTER_REPORT,
                CacheConstants.HM_CAND_SCORE_LOG_NULL);
    } catch (HMCISException e) {
        e.printStackTrace();
    }
}

public static void addtoQueue(ScoreLoggingObject scoringObject) {
    queue.add(scoringObject);
    if (firstTime) {
        synchronized (firstTime) {
            if (firstTime) {
                createInstance();
                logDaoSingleton.setDaemon(false);
                logDaoSingleton.start();
                firstTime = false;
            }
        }
    }
}

public void run() {
    try {
        while (true) {
            try {
                if (null != queue && queue.size() > 0) {
                    logData(queue.poll());
                } else {
                    try {
                        Thread.sleep(2 * 60 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                // Do nothing.
            }
        }
    } catch (Throwable e) {
        firstTime = true;
    }
}

private void logData(ScoreLoggingObject scoreLoggingObject) {

    }
}

}

エラーはlogData(queue.poll());にあります。

4

1 に答える 1

2

この方法には少なくとも 3 つの問題があります。

public static void addtoQueue(ScoreLoggingObject scoringObject) {
    queue.add(scoringObject);
    if (firstTime) {
        synchronized (firstTime) {
            if (firstTime) {
                createInstance();
                logDaoSingleton.setDaemon(false);
                logDaoSingleton.start();
                firstTime = false;
            }
        }
    }
}

すなわち

  1. LinkedListロックなしでに追加していること。LinkedList同時実行セーフ コレクションではありません。ConcurrentSkipLinkedListより良いコレクションとしてお試しください。

  2. あなたは二重チェックのロックを使用して読んfirstTimeでいます...これには、信じられないかもしれない副作用がある可能性があります...「Java Concurrency in Practice」、特に32ページのYuck-faceリストを見てください。何を予測してみてくださいそのプログラムは本を読む前に出力します。それから説明を読んでください。残念ながら、JVM には同期点間で操作を並べ替える権利があることを指摘するとき、その例の影響を台無しにする必要があります。その結果、同期ブロック内の操作は任意の順序で実装できます...たとえば、次の順序で発生する可能性があります(そうではない可能性がありますが、この順序で実行した場合、JVM 実装は引き続き有効です)

        synchronized (firstTime) {
            if (firstTime) {
                firstTime = false;
                createInstance();
                logDaoSingleton.setDaemon(false);
                logDaoSingleton.start();
            }
        }
    

    createInstance() メソッドでスローされた例外があるとどうなりますか?

    それが私だったら、JVM に順序付けを強制する を作成firstTimeすることでそれを修正します (ただし、それでも再確認が必要です!)volatile

  3. firstTimeBooleanブール値の場合、プールされたインスタンスを使用する自動ボクシングによって初期化されるため、二重チェックされたロックは実際にはありsynchronized (Boolean.TRUE)ませんsynchronized (firstTime)。さらに、非最終フィールドで同期するのは悪い形式です。問題があることがわかるまでaddToQueue、メソッドを同期させたいだけかもしれません。

TL;DR ロックを「賢く」しようとしています...常に悪い計画です...特に、賢くする必要があることを知る前に。うまくいく可能性がある最も単純なことを書いてから、残りの問題に取り掛かります。次に、パフォーマンスの問題がどこにあるかを確認します...このクラスでのロックについて心配する必要があるのはそのときだけです。

于 2012-11-26T09:23:40.937 に答える