执行者在单身课上等待

时间:2013-06-27 07:32:43

标签: java singleton executorservice

我已经实现了一个单例(管理器)来管理一些相关的任务,在这个管理器里我正在使用一个执行器来同时处理10个任务,我使用的是无限制的linkedBlockingQueue,而且到目前为止工作正常,但是现在我需要为执行程序队列设置一个限制,因为我有很多任务(数十万个任务),而且我不想把它们全部放在我的队列中导致我出现性能问题,所以我做了什么:

这是我的执行官:

public class MyThreadPoolExecutor extends ThreadPoolExecutor {

public MyThreadPoolExecutor(int corePoolSize, BlockingQueue<Runnable> workQueue) {
    super(corePoolSize, corePoolSize + 5, 500, TimeUnit.MILLISECONDS, workQueue);
}


@Override
protected void beforeExecute(Thread t, Runnable r) {
    super.beforeExecute(t, r);
    //Do something to my task
}

@Override
protected void afterExecute(Runnable r, Throwable t) {
    super.afterExecute(r, t);
    if(t != null) {
        // 
    } else {
        //Do something to my task
    }
}
}

这是我的经理:

public final class MyManager {

private static MyManager manager = new MyManager();
public static final int queueMaxSize = 100;
private BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(queueMaxSize);
private ExecutorService executor = new MyThreadPoolExecutor(10, workQueue);


/**
 * constructor
 */
private MyManager() {}

public static MyManager getInstance(){

    if (manager == null){
        synchronized(MyManager.class){
            if (manager == null){
                manager = new MyManager();
            }
        }
    }
    return manager;
}

/**
 */
public void executeTask(Integer key){
    executeTask(key, Locale.getDefault());
}

/**
 */
public void executeTask(Integer key, Locale locale) {
    Tasker task = new Tasker(key, locale);
    executor.execute(task);
}
}

这里是要求完成任务的班级:

public class MyClass {

public void doTasks() {
    //geting my tasks in array of list, its holding more than 900 000 tasks,
    //sometimes its holding up to 10 million task like :
    MyManager.getInstance().isFull() {\\wait, then ask again}

    ArrayList<Integer> myTasks = getAllTasksIds();

    for(Integer id : myTasks) {
        //if i perform a waiting here it will be waiting for ever.
        MyManaget.getInstance().executeTask(id);
    }
}

}

我想要等待执行者直到完成队列任务,然后再重新填满它。

但问题是当我尝试根据队列大小等待时,执行器将无法工作,并且它会永远等待,因为队列仍然已满。

2 个答案:

答案 0 :(得分:1)

为什么不使用有界阻塞队列(即指定BlockingQueue的边界)?如果使用有界阻塞队列(您可以自行选择其大小),则生产者将在队列已满时阻止,并在从队列中使用任务时继续发布任务。这样,您可以避免过多地将太多东西放到队列中,但也避免在队列上放置太少的东西。这就是阻止队列的重点......

答案 1 :(得分:0)

我测试了你的代码,但是我没有使用ArrayBlockingQueue,而是使用它进行扩展...而且它有效。试试吧:

public static class MyBlockingQueue extends ArrayBlockingQueue<Runnable> {

    private static final long serialVersionUID= -9016421283603545618L;

    public static Lock lock= new ReentrantLock();
    public static Condition condition= lock.newCondition();
    public static volatile Boolean isWaiting= false;

    public MyBlockingQueue(int capacity) {
        super(capacity, true);
    }

    @Override
    public boolean offer(Runnable e) {
        if (remainingCapacity() == 0) {
            try {
                isWaiting= true;
                condition.await();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
        return super.offer(e);
    }

    @Override
    public Runnable take() throws InterruptedException {
        Runnable take= super.take();
        if (remainingCapacity() > 0 && isWaiting) {
            isWaiting= false;
            condition.signal();
        }
        return take;
    }

}
相关问题