java - 信号量被多次中断的问题

标签 java multithreading

我有一个信号量限制用户一次下载 n 个文件。每个文件都在单独的线程中下载。

编辑:修改示例以便正确发布

import java.util.concurrent.Semaphore;
public void downloadFile() {
    Thread downloadThread = new Thread() {
        boolean bSemaphoreAcquired = false;
        public void run() {
            try {
                semaphore.acquire();
                bSemaphoreAcquired = true;
                // do the download
            } catch (InterruptedException e) {
            } finally {
                if (bSemaphoreAcquired) semaphore.release();
            }
        }
    };
    // add download thread to the list of download threads
    downloadThread.start();
}

现在,一旦获得所有信号量许可,任何新的下载都将等待先前的下载完成。

当用户选择取消正在等待获取调用的下载时,我调用 interrupt() 方法来终止该下载线程。 我面临的问题是,一旦这个信号量被中断,它就不会第二次抛出 InterruptedException 异常!!任何创建的新线程都将永远等待 acquire 方法!

Sequence of events (Semaphore that permits 2 threads)
- thread 1 downloading
- thread 2 downloading
- thread 3 waiting on acquire()
- thread 3 is cancelled (interrupt() is called). InterruptedException is thrown and the thread exits
- thread 4 is created and is now waiting on acquire()
- thread 4 is cancelled (interrupt() is called). InterruptedException IS NOT THROWN ANYMORE!!!

这是线程 4 的堆栈跟踪

Semaphore$FairSync(AbstractQueuedSynchronizer).fullGetFirstQueuedThread() line: 1276    
Semaphore$FairSync(AbstractQueuedSynchronizer).getFirstQueuedThread() line: 1232    
Semaphore$FairSync.tryAcquireShared(int) line: 201  
Semaphore$FairSync(AbstractQueuedSynchronizer).acquireSharedInterruptibly(int) line: 1142   
Semaphore.acquire() line: 267
FileDownloadManager$1.run() line: 150   

为什么线程4没有收到异常?

最佳答案

我建议使用标准线程池而不是信号量。 您的解决方案的问题在于,无论您是否达到最大限制,您都会创建一个新线程。因此,如果您有 1000 个并发请求,您将创建 1000 个线程,这真的很浪费。

改为尝试这样的事情:

    ExecutorService executorService = Executors.newFixedThreadPool(5);
    executorService.submit(new Runnable() {
        public void run() {
            // do download
        }
    });

关于java - 信号量被多次中断的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1226224/

相关文章:

java - 我使用了cursor_loop : loop in sql stored procedure its not fetching all 15 rows it fetch one row only

java - 从android中的自定义适配器获取复选框的ID?

java - 检测插入的 usb 并使用 java 在 linux 中读取其文件

java - 如何从 Java Scanner 输入中获取第二个单词?

c++ - OpenMP:共享同一算法的单线程和多线程实现

java - JSP/Liferay 的 Jquery 进度条实现

java - 以正确的方式实现 Event-Dispatch-Thread

java - 线程被多次调用

Java 同步

线程退出 while 循环后的 android 守护进程线程