我是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();
}
}
答案 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)
希望这有帮助。