使用计时器

时间:2016-03-14 20:42:12

标签: java timer timertask

Producer在Reader的Queue中添加要处理的文件。读者一个接一个地处理它们。这里使用Timer计划这些Producer和Reader。 目前,当队列已满时,生产者将等待读者在下一个计划中被调用并读取该值。

以下是代码的简化版本:

移除

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);
}

Adder 修改后的代码:

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));
    }
}

这会产生以下输出:

Done
Queue is empty to remove
Adding: 7 is :true
Adding: 3 is :true
Adding: 7 is :true
Adding: 2 is :true
Adding: 2 is :true
Adding: 7 is :true
Adding: 6 is :true
Adding: 0 is :true
Adding: 7 is :true
Adding: 6 is :true
Exception in thread "Timer-1" java.lang.IllegalStateException: Task already scheduled or cancelled
    at java.util.Timer.sched(Unknown Source)
    at java.util.Timer.scheduleAtFixedRate(Unknown Source)
    at task.Remover.restart(Remover.java:37)
    at task.Worker.add(Adder.java:21)
    at task.Adder.run(Adder.java:10)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)
Removing :7
Removing :3

重新安排时,add()的{​​{1}}会抛出异常并退出。 如何重新安排Adder的{​​{1}}?这个例外的原因是什么?

PS: 如果您建议更好的TimerTask模型或使用Remover,我们欢迎您。但是我对这段代码中的问题更感兴趣了!

0 个答案:

没有答案