使用 Semaphore 运行时出现 java.util.NoSuchElementException

标签 java multithreading semaphore

我有一个包含 10 个元素的队列,我启动了 100 个线程,其中 6 个线程可以并发运行,由信号量控制。当每个线程运行时,它会获取头元素,然后将其添加到尾部。但有时我会遇到这个异常:

java.util.NoSuchElementException
 at java.util.LinkedList.removeFirst(LinkedList.java:270)
 at java.util.LinkedList.remove(LinkedList.java:685)
 at IBM.SemApp$1.run(SemApp.java:27)
 at java.lang.Thread.run(Thread.java:745)
import java.util.LinkedList;    
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.Semaphore;

public class SemApp {
public static void main(String[] args) {

    Queue queueB = new LinkedList<>();
    for (int i = 0; i < 10; i++) {
        queueB.add("Object " + i);
    }

    Runnable limitedCall = new Runnable() {
        final Random rand = new Random();
        final Semaphore available = new Semaphore(6);
        int count = 0;

        public void run() {
            int time = rand.nextInt(15);

            try {
                available.acquire();
                String A = (String) queueB.remove();
                queueB.add(A);
                available.release();
                count++;
                System.out.println(count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    for (int i = 0; i < 100; i++) {
        new Thread(limitedCall).start();
    }
}
}

我做错了什么?

最佳答案

问题是 LinkedList 不是线程安全的结构。

因此,它不应该被多个并发线程共享和修改,因为 queueB 上的更改可能无法正确“传达”到其他线程。

尝试使用 LinkedBlockingQueue相反。

此外,出于同样的原因,使用 AtomicLong 进行 count :它在多个线程之间共享,并且您希望避免竞争条件。

关于使用 Semaphore 运行时出现 java.util.NoSuchElementException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31881642/

相关文章:

c++ - Deadline_timers 的非阻塞 boost io_service

php - 如何使我的文件上传后端脚本(PHP、MySQL)线程安全?

Python如何让两个不同的线程(A类,B类)共享一个串口

在多线程编程中更改值

java - 添加有关新主机的信息

java - 我在解包时收到 'CKR_WRAPPED_KEY_INVALID' 错误。如何将 AES key 解包为 DES2 key ?

Java计算楼梯的最大步数并跳过楼梯

java - 有人可以向我解释一下在 Java 中为什么 0.6 <0.6f 但 0.7is >=0.7f

java多线程学习资源

c# - SemaphoreSlim.WaitAsync 在 try block 之前/之后