gpt4 book ai didi

java - java中的队列错误

转载 作者:行者123 更新时间:2023-12-02 07:26:06 25 4
gpt4 key购买 nike

我通过一个单例类实现了一个异步线程,其中存在一个队列,我向其中添加日志记录对象。但它给出了在 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());

最佳答案

这种方法至少存在三个问题:

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

  1. 您要添加到没有锁的LinkedListLinkedList 不是并发安全集合。尝试使用 ConcurrentSkipLinkedList 作为更好的集合。

  2. 您正在阅读使用双重检查锁定的 firstTime...这可能会产生您可能不相信的副作用...去看看“Java 并发实践”特别是第 32 页上的 Yuck-face 列表。在阅读本书之前,尝试预测该程序将输出什么。然后阅读解释。不幸的是,当我指出 JVM 有权在同步点之间重新排序操作时,我将不得不破坏该示例的影响。因此,结果是同步块(synchronized block)中的操作可以按任何顺序实现...例如,它们可以按以下顺序发生(可能不是,但 JVM如果按照这个顺序执行,实现仍然有效)

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

    如果 createInstance() 方法抛出异常会发生什么?

    如果是我,我会通过将 firstTime 设置为 volatile 来解决这个问题,这将强制 JVM 遵守顺序(尽管您仍然需要仔细检查!)

  3. firstTime 是一个通过自动装箱初始化的 Boolean,对于 Boolean 使用池实例,因此您的双重检查锁实际上是同步的( Boolean.TRUE) 且未同步 (firstTime)。此外,在非最终字段上进行同步是一种不好的形式,因为它几乎从不执行您希望它执行的操作。您可能只想同步 addToQueue 方法,直到您知道有问题。

TL;DR,您试图通过锁定变得“聪明”……总是一个糟糕的计划……尤其是在您知道自己需要变得聪明之前。写出可能可行的最简单的东西,然后继续解决其余的问题。然后看看性能问题出在哪里......只有这样你才应该担心这个类中的锁定。

关于java - java中的队列错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13561151/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com