Java 如果LinkedList被大量线程快速添加/删除,对象会丢失吗?
听起来像个愚蠢的问题。我刚开始使用Java并发 我有一个LinkedList,它充当任务队列,由多个线程访问。它们移除并执行first(),其他线程则放置更多任务(.add())。任务可以让线程将它们放回队列 我注意到,当有很多任务并且它们被大量放回队列中时,我最初添加到队列中的任务数量并不是原来的数量,1,有时2缺失 我检查了所有内容,并同步了每个关键部分+notifyAll() 已将LinkedList标记为“volatile” 确切的数字是384个任务,每个任务被放回3072次 如果有少量的任务&返回,则不会出现问题。另外,如果我完成了System.out.println()所有步骤,那么它就不会再发生了,因此我无法调试 是否有可能LinkedList.add()不够快,因此线程不知何故错过了它 简化代码:Java 如果LinkedList被大量线程快速添加/删除,对象会丢失吗?,java,multithreading,concurrency,Java,Multithreading,Concurrency,听起来像个愚蠢的问题。我刚开始使用Java并发 我有一个LinkedList,它充当任务队列,由多个线程访问。它们移除并执行first(),其他线程则放置更多任务(.add())。任务可以让线程将它们放回队列 我注意到,当有很多任务并且它们被大量放回队列中时,我最初添加到队列中的任务数量并不是原来的数量,1,有时2缺失 我检查了所有内容,并同步了每个关键部分+notifyAll() 已将LinkedList标记为“volatile” 确切的数字是384个任务,每个任务被放回3072次 如果有少量
public void callByAllThreads() {
Task executedTask = null;
do
{
// access by multiple thread
synchronized(asyncQueue) {
executedTask = asyncQueue.poll();
if(executedTask == null) {
inProcessCount.incrementAndGet(); // mark that there is some processing going on
}
}
if(executedTask != null) {
executedTask.callMethod(); // subclass of task can override this method
synchronized(asyncQueue) {
inProcessCount.decrementAndGet();
asyncQueue.notifyAll();
}
}
}
while(executedTask != null);
}
该任务可以覆盖callMethod:
public void callMethodOverride() {
synchronized(getAsyncQueue()) {
getAsyncQueue().add(this);
getAsyncQueue().notifyAll();
}
}
LinkedList
绝对不是线程安全的;您无法在多线程中安全地使用它。这不是“足够快”的问题,而是一个线程所做的更改对其他线程可见的问题。将其标记为volatile无济于事;这只会影响对正在更改的LinkedList
的引用,而不会影响对LinkedList
内容的更改
考虑
ConcurrentLinkedQueue
或ConcurrentLinkedQueue
LinkedList
绝对不是线程安全的;您无法在多线程中安全地使用它。这不是“足够快”的问题,而是一个线程所做的更改对其他线程可见的问题。将其标记为volatile无济于事;这只会影响对正在更改的LinkedList
的引用,而不会影响对LinkedList
内容的更改
考虑ConcurrentLinkedQueue
或ConcurrentLinkedQueue
来自:
请注意,此实现是不同步的。如果多个线程同时访问一个链表,并且至少有一个线程在结构上修改链表,则必须在外部对其进行同步
i、 e.您应该同步访问列表。您说您是,但如果您看到项目“丢失”,那么您可能没有正确同步。您可以使用一个框架类来完成它,而不是尝试这样做
。。。如果您总是删除下一个可用(第一个)项(实际上是生产者/消费者实现),那么您可以使用一个实现,这保证是线程安全的,并且具有在一个项可用之前阻止消费者的优点。例如ArrayBlockingQueue
对于非阻塞线程安全队列,您可以查看
标记列表实例变量volatile
与您的列表是否同步以进行变异方法(如add
或removeFirst
)无关volatile
只是为了确保该实例变量的读/写在线程之间正确通信,并在线程内正确排序。请注意,我说的是该变量,而不是该变量的内容(请参见)来源:
请注意,此实现是不同步的。如果多个线程同时访问一个链表,并且至少有一个线程在结构上修改链表,则必须在外部对其进行同步
i、 e.您应该同步访问列表。您说您是,但如果您看到项目“丢失”,那么您可能没有正确同步。您可以使用一个框架类来完成它,而不是尝试这样做
。。。如果您总是删除下一个可用(第一个)项(实际上是生产者/消费者实现),那么您可以使用一个实现,这保证是线程安全的,并且具有在一个项可用之前阻止消费者的优点。例如ArrayBlockingQueue
对于非阻塞线程安全队列,您可以查看
标记列表实例变量
volatile
与您的列表是否同步以进行变异方法(如add
或removeFirst
)无关volatile
只是为了确保该实例变量的读/写在线程之间正确通信,并在线程内正确排序。请注意,我说过变量,而不是该变量的内容(请参阅)LinkedList不是线程安全的,因此,是的,多个线程同时访问它会导致问题。同步关键部分可以解决这个问题,但由于您仍然存在问题,您可能在某些地方犯了错误。尝试将其包装到集合中。synchronizedList()以同步所有方法调用。LinkedList不是线程安全的,因此是的,多个线程同时访问它会导致问题。同步关键部分可以解决这个问题,但由于您仍然存在问题,您可能在某些地方犯了错误。尝试将其包装到集合中。synchronizedList()以同步所有方法调用。链表是线程安全的,如果它适合您的需要,您可以使用它,这似乎是可能的
正如文件所说
基于链接节点的无限线程安全队列。这个队列
订单元素FIFO(先进先出)。队列的头是
在队列中停留时间最长的元素。尾巴
队列是队列中最短的元素
时间在队列的尾部插入新元素,然后
队列检索操作获取队列头部的元素。A.
当许多线程需要时,ConcurrentLinkedQueue是一个合适的选择
分享