首页 > 解决方案 > 以特定条件和时间运行线程

问题描述

我想创建一个条件,当用户下订单时,有一个线程运行 20 秒以检查数据库是否付款状态已完成或待处理,如果完成,则线程将停止,如果仍处于待处理状态,则线程将继续运行 20 秒并更新数据库中的状态以取消,我正在使用 mybatis 和 XML 映射器

这是我的代码

public class PaymentCheck implements Runnable{
   private String username;
    public PaymentCheck(String username) {
        this.username = username;
    }

    @Override
    public void run() {
        SqlSession session = MyBatisUtil.getSqlSessionFactory().openSession();
        Booking bookStatus =  session.selectOne("User.check",username);

        String status = bookStatus.getPayment_status();
        while (status.equalsIgnoreCase("pending")){
            final Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                int i = 6; // Time in seconds

                public void run() {
                    System.out.println(i--);
                    if (i < 0) {
                        timer.cancel();

                    }
                }
            }, 0, 1000);
        }
    }
}

这是我在控制器中的代码

@RequestMapping(value = "/Booking", method = RequestMethod.POST,consumes = "application/json", produces = "application/json")
public ResponseEntity<?> Booking(@RequestBody JSONObject jobj, @RequestHeader(HEADER)  String header) throws RestClientException, JsonProcessingException {

    String username = userRepo.claimToken(SECRET,PREFIX,header);
    jobj.put("username",username);
    HttpHeaders headers = new HttpHeaders();
    MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
    headers.setContentType(type);
    System.out.println(jobj.toString());
    HttpEntity<JSONObject> formEntity = new HttpEntity<JSONObject>(jobj, headers);
    JSONObject json = restTemplate.postForEntity("http://localhost:8080/hotel/Booking", formEntity, JSONObject.class).getBody();
    String message = String.valueOf(json.get("Booking Status"));

    if (!message.equalsIgnoreCase("Failed")) {
        System.out.println("json:" + json.toString());
        System.out.println(username);
        PaymentCheck tq = new PaymentCheck(username);
        tq.run();
        return new ResponseEntity<>(json,HttpStatus.CREATED);
    }else{

        return new ResponseEntity<>(json,HttpStatus.CREATED);
    }


}

这是数据库

在此处输入图像描述

它没有显示任何错误,但也没有改变任何东西......

标签: javamultithreadingmavenmybatis

解决方案


你似乎过于复杂了。

问题 1:您的线程每秒轮询一次,但控制器响应在响应客户之前没有等待更新发生。所以投票没有意义。

问题 2:您的线程实际上并没有更新数据库。

解决方案

  1. 在主线程中执行检查,轮询然后响应。
  2. 设置定时任务单次执行20秒后执行更新。

使用通用 JDBC 的解决方案 2 的示例代码

private Timer timer = new Timer();

@RequestMapping(value = "/Booking", method = RequestMethod.POST,consumes = "application/json", produces = "application/json")
public ResponseEntity<?> Booking(@RequestBody JSONObject jobj, @RequestHeader(HEADER)  String header) throws RestClientException, JsonProcessingException {

    String username = userRepo.claimToken(SECRET,PREFIX,header);
    jobj.put("username",username);
    HttpHeaders headers = new HttpHeaders();
    MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
    headers.setContentType(type);
    System.out.println(jobj.toString());
    HttpEntity<JSONObject> formEntity = new HttpEntity<JSONObject>(jobj, headers);
    JSONObject json = restTemplate.postForEntity("http://localhost:8080/hotel/Booking", formEntity, JSONObject.class).getBody();
    String message = String.valueOf(json.get("Booking Status"));

    if (!message.equalsIgnoreCase("Failed")) {
        System.out.println("json:" + json.toString());
        System.out.println(username);
        TimerTask tt = new PaymentCheck(username);
        timer.schedule(tt, 20000);
        return new ResponseEntity<>(json,HttpStatus.CREATED);
    }else{
        return new ResponseEntity<>(json,HttpStatus.CREATED);
    }
}

public class PaymentCheck extends TimerTask {

   private static final MYQUERY = "update User.check set payment_status = 'cancelled' where payment_status = 'pending' and user = ?";

   private String username;

   public PaymentCheck(String username) {
       this.username = username;
   }

    @Override
    public void run() {
        try (Connection cn = ...) {
            try (Statement stmt = new PreparedStatement(MYQUERY))
            {
                stmt.setString(1, username);
                stmt.execute();
                cn.commit();
            }
        }
    }
}



推荐阅读