在最近的项目中,遇到一个关于线程的问题:系统中包括许多线程,这些线程主要是获取不同的数据,但每次过一阵子就发现线程获取的数据混乱了,还有就是可能一个线程突然获取不到数据了。针对这些情况进行线程问题查错。
线程获取数据混乱
一般线程获取的数据混乱,主要由于线程直接数据/资源共享导致的,所以这个问题需要查看代码是否存在线程间数据共享的问题,最后发现以下问题:public static File replace(String inFileName, Map<String,String> paras) throws IOException, UnsupportedEncodingException { File inFile = new File(inFileName); BufferedReader in = new BufferedReader(new InputStreamReader( new FileInputStream(inFile), "utf-8")); File outFile = new File(inFile + ".tmp"); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))); String reading=null; Entry<String,String> entry=null; while ((reading = in.readLine()) != null) {//一行行替换需要传入的参数 Iterator it =paras.entrySet().iterator(); while(it.hasNext()){//遍历需要传入的参数 entry= (Entry<String,String>) it.next(); reading=reading.replaceAll(entry.getKey(), entry.getValue()); } out.println(reading); } out.close(); in.close(); //infile.delete(); //删除源文件 //outfile.renameTo(infile); //对临时文件重命名 return outFile; }
这部分代码实现了对请求参数的替换,是使用了一个临时文件进行替换的,而文件是在多个线程直接是共享的,所以在参数替换过程中将会发送参数错误。
一个线程突然获取不到数据
一个线程突然间获取不到数据,可能存在的原因包括线程存在未处理的异常,线程抛出异常后导致线程直接挂了,或者是多个线程访问同一资源导致多个线程都block了等。为了确定是什么原因导致的,我们使用java自带的jvisualvm工具查看线程信息。以下是Tomcat的所有线程:
点击线程Dump,查看每一个线程的实时情况,实时情况数据如下:
找到出问题的线程的信息,发现线程处于BLOCK状态,已经阻塞了,而正常的进程一般处于RUNNING、WAITING等状态,而具体导致处于BLOCK的代码为以下代码段:
public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inStream.read(buffer)) !=-1 ){
outStream.write(buffer, 0, len);
}
byte[] data = outStream.toByteArray();//网页的二进制数据
outStream.close();
inStream.close();
return data;
}
存在原因为输出流没有结束,一直处于while死循环中(具体原因可能是数据过长)。于是选择改成wsimport方式获取web service数据,从而避免自己拼串,组织参数去请求数据。