迫于无奈我使用了多线程
前言
项目上很多代码都是在原有代码的基础上做修改,以尽快满足需求,最近在修改公司代码的时候,我在调试一个JSP页面,给页面加了一个日期,然后这个日期会赋值给另一个表的字段,是一个很简单的需求,但是另一个表的那条数据是延迟产生的,至于是怎么延迟的,我还没能一步步调试出来,只知道确实是延迟,但是是在哪一段代码延迟的,我是真的找不到了,因为单步调试JS然后跟踪断点,肯定是没错的,但就是这样一步步调试,我还是没能找到哪一步进行了延迟操作,我只是觉得应该是ajax异步导致的,我对这个问题研究了很久,还是没能研究好公司的源代码,于是我打算铤而走险,创建线程来判断什么时候产生了那条数据,然后进行赋值,算是“曲线救国”吧!
关于多线程的理解
我在练习多线程开发的时候,并没有应用到实际的业务需求上,所以理解不深刻。但是经常可以遇到的时候,很多时候不清楚某一条数据或者是某段代码何时执行出现,但是整个主程序又不能在这里Sleep
等待,于是就需要一个可以返回的,异步的代码段,也就是多线程,主程序可以正常结束,新建的线程继续等待,直到这条数据可以返回为止。
这里有个隐藏的异常,就是如果新建的线程一直等待不到数据,那么很可能会卡死在判断那里,造成大量线程产生而无法结束。
示意图
如果是延迟产生数据 ,此时要么等待,要么赋空值。如果是等待,则整个程序都在等这段代码,于是延迟产生的数据还是不能产生,而赋空值就会不满足需求。
代码
package cn.caeser.Ajax;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.DateFormat;
public class CaeThreadCharge extends BaseRequest {
private TargetFromWeb ajaxResponse;
@Override
public void myRequest(HttpServletRequest arg0, HttpServletResponse arg1, ServletContext servletContext) throws ServletException {
ajaxResponse=new TargetFromWeb(arg0, arg1);
String whichMethod=ajaxResponse.getRequestParameter("whichMethod","");
switch (whichMethod) {
case "changeDate":
changeDate();
break;
default:
break;
}
}
private void changeDate(){
// 获取消费编号
String customIdStr = ajaxResponse.getRequestParameter("customId","");
// 工人编号
String workerNumber = ajaxResponse.getRequestParameter("workernumber","");
// 前端选择的日期
String choosenDate = ajaxResponse.getRequestParameter("choosendate","");
if ("".equals(customIdStr)||"".equals(workerNumber)||"".equals(choosenDate)){
// 提前判空,增加返回出口,减少大段的括号
return;
}
// 创建线程循环查找是指定数据
Thread getSampleIdThread=new Thread(new GetTargetItemThread(this,customIdStr,choosenDate,workerNumber));
// 启动线程
getSampleIdThread.start();
}
class GetTargetItemThread implements Runnable{
// 传值类
private Integer fwt;
private String customIdStr;
private String choosenDate;
private String workerNumber;
GetTargetItemThread(Integer ofwt,String sa,String sb,String sc){
this.fwt=ofwt;
this.customIdStr=sa;
this.choosenDate=sb;
this.workerNumber=sc;
}
public void run() {
StringBuilder sbGetCustomId = new StringBuilder();
DataMap dmGetMapById=null;
sbGetCustomId.append("select customId from custom where customId='"+customIdStr+"' and workerNumber='"+workerNumber+"'");
do{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dmGetMapById = fwt.mMap;
// 判断是否查找到指定数据
}while(!(dmGetMapById!=null&&dmGetMapById.size()>0));
// 如果查找到
System.out.println("赋值");
}
}
}
代码解释
我是通过实现Runnale接口
来创建线程的,当do while循环
结束之后,整个run
方法里的代码执行结束,线程的代码就执行到结尾了。
这里的变量和参数都是我自己修改后再展示的,不然我也不可能把公司里的代码拿出来展示。
为了减少大段的括号包裹代码段,我增加了代码返回的出口,以增加代码的可阅读性。
总结
其实我也只是记录一下,一个非常常见的业务需求是如何为了加快项目进度快速实现的方式,大部分赶进度其实都是这样的,可能我这份代码确实不够优雅,因为主要原因还是我没能读懂所有公司的源码,不能在延迟产生数据的下面加上赋值代码,我们在实现业务的时候,大部分情况都是尽量避免修改源码,尽量只增加不减少,尽量只往整体架构上“插入”代码。