我有一个信号量限制用户一次下载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异常!创建的任何新线程都将永远等待获取方法!
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没有收到异常?
答案 0 :(得分:2)
我建议使用标准线程池而不是信号量。 您的解决方案的问题是无论您是否达到最大限制,都会创建一个新线程。因此,如果您有1000个并发请求,您将创建1000个线程,这真的很浪费。
而是尝试这样的事情:
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(new Runnable() {
public void run() {
// do download
}
});
答案 1 :(得分:0)
你是否在捕获中释放了信号量?
为什么不把try-catch放在aquire-release中。不知道java做了什么,但不是更合乎逻辑。这样,try ... catch中的任何问题总是以释放信号量结束。