我们有一个大型文本文件,其中每行需要密集的process
。设计是使用class
来读取文件,并通过thread
将每行的处理委托给thread pool
。一旦池中没有空闲线程进行处理,就应该阻止文件阅读器类读取下一行。所以我需要一个blocking thread pool
在当前实现中,ThreadPoolExecutor.submit()
和ThreadPoolExecutor.execute()
方法在配置的#个线程忙碌后抛出RejectedExecutionException
异常,如下面的代码片段所示。
public class BlockingTp {
public static void main(String[] args) {
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
ThreadPoolExecutor executorService= new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, arrayBlockingQueue);
int Jobs = 10;
System.out.println("Starting application with " + Jobs + " jobs");
for (int i = 1; i <= Jobs; i++)
try {
executorService.submit(new WorkerThread(i));
System.out.println("job added " + (i));
} catch (RejectedExecutionException e) {
System.err.println("RejectedExecutionException");
}
}
}
class WorkerThread implements Runnable {
int job;
public WorkerThread(int job) {
this.job = job;
}
public void run() {
try {
Thread.sleep(1000);
} catch (Exception excep) {
}
}
}
以上程序的输出
Starting application to add 10 jobs
Added job #1
Added job #2
Added job #3
Added job #4
Added job #5
Added job #6
RejectedExecutionException
RejectedExecutionException
RejectedExecutionException
RejectedExecutionException
有人可以提出一些建议,即如何实施阻止线程池。
答案 0 :(得分:1)
有人可以抛出一些亮光,即我如何实现阻塞线程池。
您需要在执行器服务上设置拒绝执行处理程序。
BlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
ThreadPoolExecutor executorService =
new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, arrayBlockingQueue);
// when the blocking queue is full, this tries to put into the queue which blocks
executorService.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// block until there's room
executor.getQueue().put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RejectedExecutionException("Producer thread interrupted", e);
}
}
});
因此,不是TRE抛出RejectedExecutionException
,而是调用拒绝处理程序,而处理程序又会尝试将作业放回队列中。这会阻止来电者。
答案 1 :(得分:0)
让我们再看一下你的代码:
for (int i = 1; i <= Jobs; i++)
try {
tpExe.submit(new WorkerThread(i));
System.out.println("job added " + (i));
} catch (RejectedExecutionException e) {
System.err.println("RejectedExecutionException");
}
所以 - 当你尝试提交,并且池正忙时,会抛出该异常。如果你想环绕它,它可能看起来像:
public void yourSubmit(Runnable whatever) {
boolean submitted = false;
while (! submitted ) {
try {
tpExe.submit(new WorkerThread(whatever));
submitted = true;
} catch (RejectedExecutionException re) {
// all threads busy ... so wait some time
Thread.sleep(1000);
}
换句话说:将该例外用作&#34;标记&#34;提交目前是不可能的。
答案 2 :(得分:0)
这适合我。
class handler implements RejectedExecutionHandler{
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
答案 3 :(得分:0)
您可以使用信号量来控制resource.Reader将通过获取信号量来读取和创建异步任务。如果每个线程都忙,读者线程将等待线程可用。
public class MyExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException, RejectedExecutionException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
}
}
}