学习是最好的投资!
个人觉得所有的软件定时都是通过轮寻来完成的,而专门开一个线程来执行这样的任务比较消耗资源,感觉下面的方案可能性能会好一些。
0.首先,我们需要一个每隔5分钟发送一个广播的“定时广播”1.当用户注册时,我们注册一个监听者去监听“定时广播”2.如果用户点击邮箱中的激活地址,则将之前注册的监听者关闭3.如果监听者第二次收到广播后,则执行任务,并取消监听
之所以要在第二次收到广播的时候执行任务,是为了保证定时在5~10分钟后能执行任务。当然这样做不能保证准确的定时时间,如果需要提高定时精度的话则可以每分钟发一次广播,甚至每秒钟发一次广播,但是该场景应该不太需要。
定时广播的实现的话,可以使用quartz等工具,甚至可以用消息队列的方式来独立这一块业务。
希望可以有所帮助,如果有不合适和有错误的地方也请尽管拍砖
用数据库做轮询,如果点击则删除对应记录
使用spring的定时器 在service层完成即可 在数据库中有一个字段在注册的时候为0注册之后调用spring的定时器在五分钟后每隔几秒扫描数据库中的的这个字段并且生成验证码 用户点击了邮箱中的地址停止定时器 我可以给你spring定时器的文档和代码
贴上一段jdk原生的定时器和触发器 Timer 和 TimerTask 是重点 在timer调用schedule时注册监听 或者 其他方法调用即可 更多 请参考JDK开发文档 文档中有详细的说明。我的这个小Demo没有取消任务.
import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class Demo { public static void main(String[] args) { Timer timer = new Timer(); Long long1 =new Long("1486308200000"); timer.schedule(new TaskDemo(), new Date(long1)); } } class TaskDemo extends TimerTask{ @Override public void run() { System.out.println("点前时间是"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); } }
这种一次性的定时器用消息队列去实现是比较适合的,实现的话是比较简单的,都有成熟的方案,Java里最不缺的就是轮子。消息队列如:RabbitMQ,ActiveMQ,RocketMQ
你这个设计有问题:
按照你的设计,每个用户的注册都要开启一个定时任务,那么如果有大量用户注册呢?定时任务实际上就是一个线程,开启大量线程会消耗太多CPU资源。
用户点击邮箱激活地址,然后销毁。如果你是将定时任务存储在JVM内的话,在集群部署的时候就会很可能失效,因为你无法保证用户注册和激活时访问到的是同一个JVM实例。
定时任务发现用户未激活,然后重新生成验证码。为何要在用户下一次点击发送邮件之前就生成?
我认为比较好的设计应该是这样的:
用户注册,用户激活状态=否
用户点击【发送激活邮件】,后台生成激活url,url里附带一个uuid,这个uuid和用户名相关联,存储起来(uuid、用户名、过期时间),然后发送邮件
用户点击邮件中激活url,访问到你的应用
你的应用得到url中的uuid,看其在数据库中是否存在、且还没过期。如果yes,获得其关联的用户名,更新用户激活状态=true,删除掉这个uuid;如果no,就啥都不干。
uuid的存储:
可以存储在数据库里,不过为了清理过期的数据,你可以另外单开一个(只需要一个)线程,每1分钟去跑一次,将数据库里过期的uuid删掉。
也可以存储在redis中,redis有一个特性,就是可以指定数据的ttl,到期了它会自动删除的,这样就用不着单开一个线程清理过期uuid了。
个人觉得所有的软件定时都是通过轮寻来完成的,而专门开一个线程来执行这样的任务比较消耗资源,感觉下面的方案可能性能会好一些。
0.首先,我们需要一个每隔5分钟发送一个广播的“定时广播”
1.当用户注册时,我们注册一个监听者去监听“定时广播”
2.如果用户点击邮箱中的激活地址,则将之前注册的监听者关闭
3.如果监听者第二次收到广播后,则执行任务,并取消监听
之所以要在第二次收到广播的时候执行任务,是为了保证定时在5~10分钟后能执行任务。当然这样做不能保证准确的定时时间,如果需要提高定时精度的话则可以每分钟发一次广播,甚至每秒钟发一次广播,但是该场景应该不太需要。
定时广播的实现的话,可以使用quartz等工具,甚至可以用消息队列的方式来独立这一块业务。
希望可以有所帮助,如果有不合适和有错误的地方也请尽管拍砖
用数据库做轮询,如果点击则删除对应记录
使用spring的定时器 在service层完成即可 在数据库中有一个字段在注册的时候为0注册之后调用spring的定时器在五分钟后每隔几秒扫描数据库中的的这个字段并且生成验证码 用户点击了邮箱中的地址停止定时器 我可以给你spring定时器的文档和代码
贴上一段jdk原生的定时器和触发器 Timer 和 TimerTask 是重点 在timer调用schedule时注册监听 或者 其他方法调用即可 更多 请参考JDK开发文档 文档中有详细的说明。我的这个小Demo没有取消任务.
这种一次性的定时器用消息队列去实现是比较适合的,实现的话是比较简单的,都有成熟的方案,Java里最不缺的就是轮子。消息队列如:RabbitMQ,ActiveMQ,RocketMQ
你这个设计有问题:
按照你的设计,每个用户的注册都要开启一个定时任务,那么如果有大量用户注册呢?定时任务实际上就是一个线程,开启大量线程会消耗太多CPU资源。
用户点击邮箱激活地址,然后销毁。如果你是将定时任务存储在JVM内的话,在集群部署的时候就会很可能失效,因为你无法保证用户注册和激活时访问到的是同一个JVM实例。
定时任务发现用户未激活,然后重新生成验证码。为何要在用户下一次点击发送邮件之前就生成?
我认为比较好的设计应该是这样的:
用户注册,用户激活状态=否
用户点击【发送激活邮件】,后台生成激活url,url里附带一个uuid,这个uuid和用户名相关联,存储起来(uuid、用户名、过期时间),然后发送邮件
用户点击邮件中激活url,访问到你的应用
你的应用得到url中的uuid,看其在数据库中是否存在、且还没过期。如果yes,获得其关联的用户名,更新用户激活状态=true,删除掉这个uuid;如果no,就啥都不干。
uuid的存储:
可以存储在数据库里,不过为了清理过期的数据,你可以另外单开一个(只需要一个)线程,每1分钟去跑一次,将数据库里过期的uuid删掉。
也可以存储在redis中,redis有一个特性,就是可以指定数据的ttl,到期了它会自动删除的,这样就用不着单开一个线程清理过期uuid了。