Java 使用计时器在队列已满时重新安排使用者

Java 使用计时器在队列已满时重新安排使用者,java,timer,timertask,Java,Timer,Timertask,Producer将要处理的文件添加到读卡器队列中。读者一个接一个地阅读并处理它们。在这里,这些生产者和读者都是使用定时器调度的。 当前,当队列已满时,生产者将等待读取器在其下一个调度中被调用并读取值 以下是代码的简化版本: 去除剂 public class Remover extends TimerTask { private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);

Producer将要处理的文件添加到读卡器队列中。读者一个接一个地阅读并处理它们。在这里,这些生产者和读者都是使用
定时器调度的。
当前,当队列已满时,生产者将等待读取器在其下一个调度中被调用并读取值

以下是代码的简化版本:

去除剂

public class Remover extends TimerTask {
    private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
    private static Remover instance = new Remover();

    public synchronized static Remover getInstance() {
        if (instance == null) {
            instance = new Remover();
        }
        return instance;
    }

    public ArrayBlockingQueue<Integer> getQueue() {
        return queue;
    }

    public void remove() {
        if (!queue.isEmpty())
            System.out.println("Removing :" + queue.poll());
        else
            System.out.println("Queue is empty to remove");
    }

    public void start() {
        Timer readTimer = new Timer();
        readTimer.scheduleAtFixedRate(Remover.getInstance(), 0, 10000);
    }

    @Override
    public void run() {
        remove();
    }
}
public class Adder extends TimerTask {
    @Override
    public void run() {
        new Worker().add();
    }
}

class Worker {
    public void add() {
        Random random = new Random();
        ArrayBlockingQueue<Integer> queue = Remover.getInstance().getQueue();
        for (int i = 0; i < random.nextInt(20); i++) {
            int value = random.nextInt(10);
            while (queue.remainingCapacity() == 0) {
                System.out.println("Queue is full! Wait for sometime!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.err.println(e.getMessage());
                }
            }
            System.out.println("Adding: " + value + " is :" + queue.add(value));
        }
    }
}
public class Tester {
    public static void main(String[] args) {
        Remover.getInstance().start();

        Timer writeTimer = new Timer();
        writeTimer.scheduleAtFixedRate(new Adder(), 0, 3000);

        System.out.println("Done");
    }
}
输出:

Done
Queue is empty to remove
Adding: 8 is :true
Adding: 0 is :true
Adding: 4 is :true
Adding: 7 is :true
Adding: 0 is :true
Adding: 6 is :true
Adding: 3 is :true
Adding: 4 is :true
Adding: 2 is :true
Adding: 5 is :true
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Removing :8
Adding: 6 is :true
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
Queue is full! Wait for sometime!
此方法的问题是生产者正在等待,直到在其下一个计划中调用删除程序

所以我想从现在开始重新安排拆卸程序。从而合理利用生产者的等待时间和去除剂的睡眠时间

为了促进这一想法,我做了以下修改:

删除程序修改代码:

private Timer readTimer = null;

public void start() {
    readTimer = new Timer();
    readTimer.scheduleAtFixedRate(Remover.getInstance(), 0, 10000);
}

public void restart() {
    readTimer.cancel(); 
    readTimer = new Timer();
    readTimer.scheduleAtFixedRate(Remover.getInstance(), 0, 10000);
}
public void add() {
    Random random = new Random();
    ArrayBlockingQueue<Integer> queue = Remover.getInstance().getQueue();
    for (int i = 0; i < random.nextInt(20); i++) {
        int value = random.nextInt(10);
        while (queue.remainingCapacity() == 0) {
            Remover.getInstance().restart();
            System.out.println("Queue is full! Restarting the remover!");
        }
        System.out.println("Adding: " + value + " is :" + queue.add(value));
    }
}
加法器修改代码:

private Timer readTimer = null;

public void start() {
    readTimer = new Timer();
    readTimer.scheduleAtFixedRate(Remover.getInstance(), 0, 10000);
}

public void restart() {
    readTimer.cancel(); 
    readTimer = new Timer();
    readTimer.scheduleAtFixedRate(Remover.getInstance(), 0, 10000);
}
public void add() {
    Random random = new Random();
    ArrayBlockingQueue<Integer> queue = Remover.getInstance().getQueue();
    for (int i = 0; i < random.nextInt(20); i++) {
        int value = random.nextInt(10);
        while (queue.remainingCapacity() == 0) {
            Remover.getInstance().restart();
            System.out.println("Queue is full! Restarting the remover!");
        }
        System.out.println("Adding: " + value + " is :" + queue.add(value));
    }
}
重新调度时,
Adder
add()
抛出异常并退出。 如何重新安排
删除程序的
时间任务
?这一例外的原因是什么

附言:
如果您建议更好的
生产者-消费者
模型或使用
执行器服务
,我将表示欢迎。但是我更感兴趣的是理解这段代码中的问题

让生产商和消费者都按时运行似乎是一种脆弱的做事方式;如果计时错误,队列将被填满。你为什么要这么做?为什么不只安排生产者,让消费者块在队列中,这样它就可以等待工作了?@Raedwald整个想法是-CSV文件被连续地放在一个文件夹中。它们必须被解析和处理。生产者正在解析,移除者正在处理。删除程序代码已作为计划任务运行。我正试图通过添加制作人来完成工作流。