-->

Java代码生成计时器

1. 背景

由于项目前端界面中需要计时器,而前端又存储不住数据,即使存储在cookis或者session里,在清空cookis后存在较大的安全隐患,所以需要后端也使用Java代码去生成计时器,同时能够实现多个计时器同时计时

2. 计时器类

点击查看代码
package com.example.pmxt.common;
//这里可以实现runable接口,也可以继承Thread类,runable与Thread的关系是实现,Thread是Runable的实现类,比Runable多了些方法,但两者并无本质区别
public class Countdown extends Thread{
        private boolean stop = false;
        private boolean pause = false;
        private int time;

        private int initialtime;
//这里可以是任何名字
        private final Object lock = new Object();

        @Override
        public void run() {
            while (!stop && time > 0) {
                while (pause) {
                    onPause();
                }
                time--;
                try {
                    Thread.sleep(1000);
                    int hh = time / 60 / 60 % 60;
                    int mm = time / 60 % 60;
                    int ss = time % 60;
                    System.out.println("还剩" + hh + "小时" + mm + "分钟" + ss + "秒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    /**
     * 这个方法只能在run 方法中实现,不然会阻塞主线程,导致页面无响应,保证只会有一个线程挂起
     */
        void onPause() {
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
//开始时间
        public int start(int time) {
            this.time=time;
            this.initialtime=time;
            new Thread(this).start();
            return time;
        }
//彻底停止计时器,无法恢复
        public void stopThread() {
            this.stop = true;
        }
//暂停时间
        public int pauseThread() {
            this.pause = true;
            return time;
        }
//恢复倒计时
        public int resumeThread() {
            this.pause = false;
            synchronized (lock) {
			//恢复挂起的线程
                lock.notify();
            }
            return time;
        }
//重置倒计时
        public void reset(){
            this.time = initialtime;
        }

//获取当前时间
        public int getTime(){
            return time;
        }
}

3. Seivice

点击查看代码
package com.example.pmxt.modules.jmzt;

import com.example.pmxt.common.BaseService;
import com.example.pmxt.common.Countdown;
import com.example.pmxt.domain.Jmzt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Time;
import java.util.*;


@Service
@Transactional
public class JmztService extends BaseService<JmztMapper, Jmzt> {

    private final JmztMapper jmztMapper;
//计时器键值对,实现多个计时器的存储
    Map<String,Object> countdowns= new HashMap<>();
//帮助前端存储变量
    Map<String,Boolean> selects = new HashMap<>();

//    int num =1;




    @Autowired
    public JmztService(JmztMapper jmztMapper) {
        this.jmztMapper = jmztMapper;
    }
//回退
    public Boolean back(String bdbh) {
        int[] a = jmztMapper.idcol(bdbh);
        System.out.println(Arrays.toString(a));
        int b = 0;
        int c = 0;
        int d = 0;
        if (a == null||a.length == 0){
            return false;
        }else if (a.length > 1) {
            b = jmztMapper.setBack(a[0]);
            c = jmztMapper.setUp(a[1]);
        } else {
            d = jmztMapper.setBack(a[0]);
        }
        return b != 0 || c != 0 || d != 0;
    }
//出价
    public boolean bid(String bdbh, String jmh, BigDecimal cj,String pmhbh,Boolean select){
        Countdown countdown = (Countdown) countdowns.get(pmhbh);
        int[] a = jmztMapper.idcol(bdbh);
        jmztMapper.bid(bdbh, jmh, cj);
        if(select){
            countdown.reset();
        }

        int[] b = jmztMapper.idcol(bdbh);
        System.out.println(Arrays.toString(a));
        System.out.println(Arrays.toString(b));
        int c;
        if (b == null||b.length - a.length == 0){
            return false;
        }else if (b.length - a.length == 1){
            if (b.length ==1) {
                return true;
            } else {
            c = jmztMapper.setOut(b[1]);
            return c!=0;
            }
        }else return false;
    }
//修改加价幅度
    public int updJjfd(String bdbh, BigDecimal jjfd){
        return jmztMapper.updJjfd(bdbh, jjfd);
    }
//开拍
    public int bdBegin(String bdbh){
        return jmztMapper.bdBegin(bdbh);
    }

//竞价记录
    public List<Jmzt> record(String bdbh){
        return jmztMapper.record(bdbh);
    }
//标的成交
    public int bdSuccess(String bdbh){
        return jmztMapper.bdSuccess(bdbh);
    }
//标的流拍
    public int bdFailure(String bdbh){
        return jmztMapper.bdFailure(bdbh);
    }

//    开始倒计时
    public int startTime(String pmhbh, Time temtime,Boolean select){
        if(countdowns.get(pmhbh) == null){
            Countdown countdown = new Countdown();
            selects.put(pmhbh,select);
            countdowns.put(pmhbh,countdown);
            int time1;
            time1 = countdown.start(temtime.getHours()*3600+temtime.getMinutes()*60+temtime.getSeconds());
            return time1;
        }else {
            Countdown countdown = (Countdown) countdowns.get(pmhbh);
            countdown.stopThread();
            countdowns.remove(pmhbh, countdown);
            return 0;
        }

//        num++;
//        int time;

//        if (select) {
//            time = jmztMapper.getByBdbh(bdbh).getYsjjsj().getHours()*3600+jmztMapper.getByBdbh(bdbh).getYsjjsj().getMinutes()*60+jmztMapper.getByBdbh(bdbh).getYsjjsj().getSeconds();
//            time1 = countdown.start(time);
//        }else {
//            time = jmztMapper.getByBdbh(bdbh).getXsjjsj().getHours()*3600+jmztMapper.getByBdbh(bdbh).getXsjjsj().getMinutes()*60+jmztMapper.getByBdbh(bdbh).getXsjjsj().getSeconds();
//            time1 = countdown.start(time);
//        }

    }
//    停止倒计时
    public int stopTime(String pmhbh){
        Countdown countdown = (Countdown) countdowns.get(pmhbh);
        if(countdown == null){
            return 0;
        }else {
            return countdown.pauseThread();
        }
    }

//    继续倒计时
    public int continueTime(String pmhbh){
        Countdown countdown = (Countdown) countdowns.get(pmhbh);
        if(countdown == null){
            return 0;
        }else {

            return countdown.resumeThread();
        }
    }

//    重置倒计时
    public Boolean resetTime(String pmhbh){
        Countdown countdown = (Countdown) countdowns.get(pmhbh);
        if(countdown == null){
            return false;
        }else {
            countdown.reset();
            return true;
        }
    }

//    注销计时器
    public Boolean delTimer(String pmhbh){
        if(countdowns.get(pmhbh) == null){
            return false;
        }else {
            Countdown countdown = (Countdown) countdowns.get(pmhbh);
            countdown.stopThread();
            countdowns.remove(pmhbh, countdown);
            return true;
        }
    }

//    获取当前时间
    public Map<String,Object> getTime(String pmhbh){
        Map<String,Object> map = new HashMap<>();
        if(countdowns.get(pmhbh) == null){
            map.put("time",0);
        }else {
            Countdown countdown = (Countdown) countdowns.get(pmhbh);
            map.put("time",countdown.getTime());
        }
        if(selects.get(pmhbh) == null){
            map.put("select","不存在");
        }else {
            map.put("select",selects.get(pmhbh));
        }
        return map;
    }
}

4. Controller类

点击查看代码
package com.example.pmxt.modules.jmzt;

import com.example.pmxt.common.ReturnResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.sql.Time;
import java.util.Map;

@RestController
@Validated
@RequestMapping("/jmzts")
public class JmztController {

    private final JmztService jmztService;

    @Autowired
    public JmztController(JmztService jmztService) {
        this.jmztService = jmztService;
    }
//回退
    @PostMapping("/back")
    public ReturnResult back(String bdbh){
        return ReturnResult.buildSuccessResult(jmztService.back(bdbh));
    }
//出价
    @PostMapping("/bid")
    public ReturnResult bid(String bdbh, String jmh, BigDecimal cj, String pmhbh,Boolean select){
        return ReturnResult.buildSuccessResult(jmztService.bid(bdbh, jmh, cj,pmhbh,select));
    }
//修改加价幅度
    @PostMapping("/updJjfd")
    public ReturnResult updJjfd(String bdbh, BigDecimal jjfd){
        return ReturnResult.buildSuccessResult(jmztService.updJjfd(bdbh, jjfd));
    }
//标的开拍
    @PutMapping("/bdBegin")
    public ReturnResult bdBegin(String bdbh){
        return ReturnResult.buildSuccessResult(jmztService.bdBegin(bdbh));
    }
//竞价记录
    @GetMapping("/record")
    public ReturnResult record(String bdbh){
        return ReturnResult.buildSuccessResult(jmztService.record(bdbh));
    }
//标的成交
    @PutMapping("/bdSuccess")
    public ReturnResult bdSuccess(String bdbh){
        return ReturnResult.buildSuccessResult(jmztService.bdSuccess(bdbh));
    }
//标的流拍
    @PutMapping("/bdFailure")
    public ReturnResult bdFailure(String bdbh){
        return ReturnResult.buildSuccessResult(jmztService.bdFailure(bdbh));
    }
//开始计时
    @PostMapping("/startTime")
    public ReturnResult startTime(String pmhbh, Time temtime,Boolean select){
        int time = jmztService.startTime(pmhbh,temtime,select);
        if (time == 0){
            return ReturnResult.buildSuccessResult("计时器已经存在,已经帮您注销,请再次点击");
        }else {
            return ReturnResult.buildSuccessResult(time);
        }
    }
//停止倒计时
    @PostMapping("/stopTime")
    public ReturnResult stopTime(String pmhbh){
        int time = jmztService.stopTime(pmhbh);
        if (time == 0){
            return ReturnResult.buildSuccessResult("计时器不存在");
        }else {
            return ReturnResult.buildSuccessResult(time);
        }
    }
//继续倒计时
    @PostMapping("/continueTime")
    public ReturnResult continueTime(String pmhbh){
        int time = jmztService.continueTime(pmhbh);
        if (time == 0){
            return ReturnResult.buildSuccessResult("计时器不存在");
        }else {
            return ReturnResult.buildSuccessResult(time);
        }
    }
//重置倒计时
    @PostMapping("/resetTime")
    public ReturnResult resetTime(String pmhbh){
        Boolean time = jmztService.resetTime(pmhbh);
        if (time){
            return ReturnResult.buildSuccessResult("重置成功");
        }else {
            return ReturnResult.buildSuccessResult("计时器不存在");
        }

    }
//注销计时器
    @PostMapping("/deleteTimer")
    public ReturnResult delTimer(String pmhbh){
        Boolean time = jmztService.delTimer(pmhbh);
        if (time){
            return ReturnResult.buildSuccessResult("删除成功");
        }else {
            return ReturnResult.buildSuccessResult("计时器不存在");
        }
    }
//获取当前时间
    @PostMapping("/getTime")
    public ReturnResult getTime(String pmhbh){
        Map<String, Object> map = jmztService.getTime(pmhbh);
        if ((int)map.get("time") == 0){
            return ReturnResult.buildSuccessResult("计时器不存在");
        }else {
            return ReturnResult.buildSuccessResult(map);
        }
    }
}

5. 出现的错误

注意上述计时器用的是继承Thread类,如果实现runable会出现在idea中没问题,二到服务器上或者用tomcat会出现暂停后无法继续的问题,错误的计时器如下:

点击查看代码
package com.example.pmxt.common;




public class countdown implements Runnable{
        private boolean stop;
        private boolean pause;
        private int time;

        private int initialtime;

        @Override
        public void run() {
            while (!stop) {
			//不加输出语句服务器会无法继续
                System.out.println("------------------");
                if (!pause) {
                    time--;
                    try {
                        Thread.sleep(1000);
                        int hh = time / 60 / 60 % 60;
                        int mm = time / 60 % 60;
                        int ss = time % 60;
                        System.out.println("还剩" + hh + "小时" + mm + "分钟" + ss + "秒");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        public int start(int time) {
            this.time=time;
            this.initialtime=time;
            new Thread(this).start();
            return time;
        }

        public void stop() {
            this.stop = true;
        }

        public int pause() {
            this.pause = true;
            return time;
        }

        public int resume() {
            this.pause = false;
            return time;
        }

        public void reset(){
            this.time = initialtime;
        }


        public int getTime(){
            return time;
        }


//        public static long getCount() {
//
//        }





}

导致原因:stop,pause没在内存中,无法改变其值,这两个在工作内存中。
解决办法有两个:1.加输出语句 2.在stop、pause属性上加volatile

详细如下:
Java基础:volatile详解

6. 后续

发现hutool也是有计时器的,不过没有用过,有需要的可以去看一下
hutool计时器

posted @   ꧁ʚ星月天空ɞ꧂  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示