一个服务器的特殊需求,求给思路

LittleLeeZi 2015-09-10 05:31:20
项目有一个需求,就是app用户会设置很多个人的待办事项,同时可以设置短信提醒,到一个设定的时间点,服务器就需要调用SMS系统发送短信,而且可以设置为每隔一段时间提醒一次。
对于这么一个需求,大家有什么思路呢?
我首先想到的是java的TimerTask,每个待办事项都单独建立一个线程执行TimerTask,但我担心这样一来会有太多太多的线程,因为用户可能会很多,而每个用户又可以有很多的待办事项。这样的线程会不会很耗资源?服务器负载会不会有问题?
其次能够节省服务器资源的就是采用定时扫描了,但这种方案的缺点也显而易见,主要是扫描的频率问题,过高加大数据库负载,过小及时性不好。
如何既能保证不耗费服务器资源,而又具备很高的及时性呢?
不知道大家有什么好的方案,java不太熟练,求指教。
...全文
178 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
cutter_point 2015-09-11
  • 打赏
  • 举报
回复
这是一个队列的问题么?
少主无翼 2015-09-11
  • 打赏
  • 举报
回复
不会,ScheduledThreadPoolExecutor内部会有多个线程去定时从队列中取出可执行的任务进行执行,delay只是将任务的执行时间往后推而已。
LittleLeeZi 2015-09-11
  • 打赏
  • 举报
回复
引用 11 楼 hqshaozhu 的回复:
[quote=引用 10 楼 hqshaozhu 的回复:] [quote=引用 7 楼 lkl713 的回复:] [quote=引用 4 楼 hqshaozhu 的回复:] 没发现JDK的ScheduledThreadPoolExecutor就是用来这么玩的吗。可以延迟,可以定时,可以周期,完全符合你的需要
这个pool中的线程如果过多的话,会出问题吗[/quote] 建议线程数==CPI核数即可,毕竟你的需要不需要非常高的实时性,而且你的每个定时任务基本都很快就可以完成,这样就不到导致太多任务同一时刻运行时,有些任务等待时间过长,如果任务耗时长的话可以在使用一个队列或者线程池来专门用来执行任务。不过还是会出现那种情况,毕竟计算机只有几个核,同一时间只能运行那么几个任务。[/quote] CPU核数[/quote] delay>0的线程在时间未到的时候会占用CPU和内存资源吗?
少主无翼 2015-09-10
  • 打赏
  • 举报
回复
引用 10 楼 hqshaozhu 的回复:
[quote=引用 7 楼 lkl713 的回复:] [quote=引用 4 楼 hqshaozhu 的回复:] 没发现JDK的ScheduledThreadPoolExecutor就是用来这么玩的吗。可以延迟,可以定时,可以周期,完全符合你的需要
这个pool中的线程如果过多的话,会出问题吗[/quote] 建议线程数==CPI核数即可,毕竟你的需要不需要非常高的实时性,而且你的每个定时任务基本都很快就可以完成,这样就不到导致太多任务同一时刻运行时,有些任务等待时间过长,如果任务耗时长的话可以在使用一个队列或者线程池来专门用来执行任务。不过还是会出现那种情况,毕竟计算机只有几个核,同一时间只能运行那么几个任务。[/quote] CPU核数
少主无翼 2015-09-10
  • 打赏
  • 举报
回复
引用 7 楼 lkl713 的回复:
[quote=引用 4 楼 hqshaozhu 的回复:] 没发现JDK的ScheduledThreadPoolExecutor就是用来这么玩的吗。可以延迟,可以定时,可以周期,完全符合你的需要
这个pool中的线程如果过多的话,会出问题吗[/quote] 建议线程数==CPI核数即可,毕竟你的需要不需要非常高的实时性,而且你的每个定时任务基本都很快就可以完成,这样就不到导致太多任务同一时刻运行时,有些任务等待时间过长,如果任务耗时长的话可以在使用一个队列或者线程池来专门用来执行任务。不过还是会出现那种情况,毕竟计算机只有几个核,同一时间只能运行那么几个任务。
zhuangqingch 2015-09-10
  • 打赏
  • 举报
回复
引用 7 楼 lkl713 的回复:
[quote=引用 4 楼 hqshaozhu 的回复:] 没发现JDK的ScheduledThreadPoolExecutor就是用来这么玩的吗。可以延迟,可以定时,可以周期,完全符合你的需要
这个pool中的线程如果过多的话,会出问题吗[/quote] 楼主还想着用“每个待办事项都单独建立一个线程”?虽然采用线程池可以启到多个处理操作独立一个线程执行。但楼主你需要注意,并不是线程越多,效率就越高。首先假设你的CPU有4核。即同一时刻只能处理4个任务,现在你的线程池开了10个线程。 假如现在你有100个待办事项定时任务在同一时刻运行。则会出现这样的场景。线程池中10个线程都会被取出来处理任务。但此时任务有100个。所以会先处理其中10个,另外90个先等待着。但10个线程有个别是线程处理完任务空闲出来时。才能继续让空闲的线程去处理90个当中的其中几个。另外这些还有个陷井。4核CPU,跑10个线程。实际上直接并行跑的只能有4个,所以为了可以实现10个线程异步跑。CPU会用上下文切换技术来回在这10个线程中切换执行。线程的切换执行是比较耗时的。所以这也是一个问题。 所以说如果你的硬件配置如果太低,而线程又太多。则会导致线程上下文切换影响效率(这种情况下,通常只比一个线程同步执行快1倍左右)。同时,另外还有一个隐藏的陷井,就是内存空间。每个线程的创建都需要占用一定的内存空间,这也是楼主需要注意的。
zhuangqingch 2015-09-10
  • 打赏
  • 举报
回复
引用 6 楼 lkl713 的回复:
[quote=引用 1 楼 zhuangqingch 的回复:] 一个独立线程就可以搞定了。起一个线程。给定一个间隔时长,如1分钟。每1分钟取出库中可以发送短信的用户进行发送。然后按规定间隔时长休眠下。抽象代码如下:

new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        //select * from user where xxxx 查找可以进行发送的用户
                        List<String> userList = new ArrayList<String>();
                        for (String uid : userList) {
                            //调用接口发送短信
                            sendSMS(uid);
                        }
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
您说的这种就是定时扫描数据库的方式,这种方式的实时性不太好吧,而且扫描过于频繁的话数据库负载也是一个问题[/quote] 嗯,这得看你项目场景了。如果用户量及并发要求比较高的场景下。这种方式会对系统有影响。你可以采用缓存的方式,将用户的待办设置信息缓存在内存中。就能解决该问题。至于你说的实时性,关键点不在于这个扫描的逻辑。假设你系统用户有500W用户。一个for循环估计也耗不了你1秒时长。你的实时性主要由你的SMS接口决定。
LittleLeeZi 2015-09-10
  • 打赏
  • 举报
回复
引用 4 楼 hqshaozhu 的回复:
没发现JDK的ScheduledThreadPoolExecutor就是用来这么玩的吗。可以延迟,可以定时,可以周期,完全符合你的需要
这个pool中的线程如果过多的话,会出问题吗
LittleLeeZi 2015-09-10
  • 打赏
  • 举报
回复
引用 1 楼 zhuangqingch 的回复:
一个独立线程就可以搞定了。起一个线程。给定一个间隔时长,如1分钟。每1分钟取出库中可以发送短信的用户进行发送。然后按规定间隔时长休眠下。抽象代码如下:

new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        //select * from user where xxxx 查找可以进行发送的用户
                        List<String> userList = new ArrayList<String>();
                        for (String uid : userList) {
                            //调用接口发送短信
                            sendSMS(uid);
                        }
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
您说的这种就是定时扫描数据库的方式,这种方式的实时性不太好吧,而且扫描过于频繁的话数据库负载也是一个问题
zhuangqingch 2015-09-10
  • 打赏
  • 举报
回复
引用 2 楼 zhuangqingch 的回复:
用户设置设置了每隔一段时间提醒一次,在库中你可以记录下关键信息,如:起始时间、周期间隔、最大提醒次数。最终用select根据当前时间判断是否符合发送要求就可以了。针对你的需求。你的app应该会限制提醒周期最小时长。一般不可能1分钟提醒一次。数据你的线程用每分钟轮询检查是可以满足需求的。最坏情况也是短信延迟1分钟发送(n个用户调接口发送短信耗时不计在内)
虽然用户的设定的是间隔一定时长重复发送。但程序可以灵活处理,不用一看到定时就往多线程、定时调度方向想。
少主无翼 2015-09-10
  • 打赏
  • 举报
回复
没发现JDK的ScheduledThreadPoolExecutor就是用来这么玩的吗。可以延迟,可以定时,可以周期,完全符合你的需要
零零三 2015-09-10
  • 打赏
  • 举报
回复
可以看下DelayQueue
zhuangqingch 2015-09-10
  • 打赏
  • 举报
回复
用户设置设置了每隔一段时间提醒一次,在库中你可以记录下关键信息,如:起始时间、周期间隔、最大提醒次数。最终用select根据当前时间判断是否符合发送要求就可以了。针对你的需求。你的app应该会限制提醒周期最小时长。一般不可能1分钟提醒一次。数据你的线程用每分钟轮询检查是可以满足需求的。最坏情况也是短信延迟1分钟发送(n个用户调接口发送短信耗时不计在内)
zhuangqingch 2015-09-10
  • 打赏
  • 举报
回复
一个独立线程就可以搞定了。起一个线程。给定一个间隔时长,如1分钟。每1分钟取出库中可以发送短信的用户进行发送。然后按规定间隔时长休眠下。抽象代码如下:

new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        //select * from user where xxxx 查找可以进行发送的用户
                        List<String> userList = new ArrayList<String>();
                        for (String uid : userList) {
                            //调用接口发送短信
                            sendSMS(uid);
                        }
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧