使用多个实例同步两个计时器(Java)

时间:2012-04-17 17:11:01

标签: java multithreading sync

我是Java的新手,过去我没有使用过线程。现在,对于我的知识水平,我有一个非常棘手的问题。

我开发了两种功能“发送邮件”和“检查邮件”。每个用户都会注册他的首选项,系统会创建两个目录,其中包含许多定期工作的指令,如

A)每1500毫秒发送一次信息

B)每1800毫秒发送一次信息

C)每3000毫秒发送一次信息

和 A)每2000毫秒检查一次消息

B)每6000毫秒检查一次消息

C)每8000毫秒检查一次消息

我尝试了许多使用线程的方法,但是我没有做到这一点。 我的问题是哪个是同步它们的最佳方法?下面是我上一次使用线程的代码。

public class MailCreatorThread extends Thread {
    @Override
    public void run() {
        CreateMail(_date); //creates a mail with _date as subject
    }
}

public class GPSThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (!_isTimeToStop) {
            try {
                while (_servicesToUpdate.size() == 0) {
                    Thread.sleep(500);
                }
                _currentService = (MyService) _servicesToUpdate.get(0)
                        .clone();
                _servicesToUpdate.remove(0);

                        MailCreatorThread mailCreatorThread = new MailCreatorThread();
                        mailCreatorThread.start();


            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

public class CheckServicesThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (!_isTimeToStop) {
            try {
                Thread.sleep(1000);
                    for (int j = 0; j < _servicesList.length; j++) {
                        MyService currentService = ((MyService) _servicesList[j]);
                        if (myService.getTimeToNextUpdate() - 1000 <= 0) {
                            _servicesToUpdate
                                    .add((MyService) currentService
                                            .clone());
                            currentService
                                    .setTimeToNextUpdate(currentService
                                            .getUpdatePeriod());
                        } else {
                            currentService
                                    .setTimeToNextUpdate(currentService
                                            .getTimeToNextUpdate() - 1000);
                        }
                }

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        stopSelf();
    }
}

2 个答案:

答案 0 :(得分:4)

您可以使用ScheduledExecutorService来执行定期任务。语法非常简单:

Runnable check = new Runnable() {
    public void run() {
        checkMessage();
    }
}
Runnable send = new Runnable() {
    public void run() {
        sendMessage();
    }
}

//since what you are doing is mostly I/O you probably want to have 
//more than one thread available so that if one operation blocks,
//the other ones can be launched in parallel

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleAtFixedRate(check, 0, 1500, MILLISECONDS);
scheduler.scheduleAtFixedRate(send, 0, 6000, MILLISECONDS);

注意:[{3}}中提到的Timer不应再使用,因为ScheduledThreadPoolExecutor已在Java 1.5中对其进行了改进,如Ozzy's answer中所述:

  

Java 5.0引入了java.util.concurrent包,其中一个并发实用程序是ScheduledThreadPoolExecutor,它是一个线程池,用于以给定的速率或延迟重复执行任务。它实际上是Timer / TimerTask组合的更通用替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化TimerTask(只需实现Runnable)。使用一个线程配置ScheduledThreadPoolExecutor使其等效于Timer。

答案 1 :(得分:3)

在java中,你有内置的Timer和TimerTask类来帮助你在一个单独的线程中重复任务。

这将创建一个Timer,它将创建自己的后台线程:

Timer t = new Timer();

然后,您可以根据需要为该计时器安排任意数量的任务,他们将共享计时器自己的线程。

这是在延迟2000ms = 2s后,您可以在计时器线程上安排单个任务的方法:

t.schedule(new TimerTask() {
    @Override
    public void run() {
        //task to perform
    }
}, 2000);

这是在延迟1秒后在计时器线程上安排重复任务的方法,并以1.5秒的间隔重复任务:

t.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        //task to perform every 1.5 seconds
    }
}, 1000, 1500);

现在您可以选择将两个任务(checkMail,sendMail)安排到同一个Timer(相同的线程),或者为每个任务提供自己的Timer(单独的线程)。

有关详细信息,请参阅java docs(http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html)

希望这有帮助。