Servlet用内部类加载多线程_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Servlet用内部类加载多线程

Servlet用内部类加载多线程

 2014/11/14 13:03:10  longhua2003  程序员俱乐部  我要评论(0)
  • 摘要:这些天,一直在做一个web小项目,也就是练习一下Servlet,昨晚,想在网站中增加一个统计访问量的功能,因为考虑到用多线程每隔一定的时间去自动的保存访问量,会更准确(因为,你不用隔一段去保存访问量,如果突然断电了,访问量就会失去了),想法是好的,但做起来,还真的不容易:以下程序是没有加载线程importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.FileNotFoundException
  • 标签:多线程 Servlet 线程
   这些天,一直在做一个web小项目,也就是练习一下Servlet,昨晚,想在网站中增加一个统计访问量的功能,因为考虑到用多线程每隔一定的时间去自动的保存访问量,会更准确(因为,你不用隔一段去保存访问量,如果突然断电了,访问量就会失去了),想法是好的,但做起来,还真的不容易:

以下程序是没有加载线程
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class InitServlet extends HttpServlet {


/**
* 关掉服务器时,会执行这个函数
*/
public void destroy() {
this.Thread_Init();
}

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();

out.println("</HTML>");

}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

this.doGet(request, response);
}

private void Thread_Init()

{
System.out.println("thread调用");

String FilePath = this.getServletContext().getRealPath("Nums.text");

try {
FileWriter fileReader = new FileWriter(FilePath);
BufferedWriter buffer = new BufferedWriter(fileReader);
// 从ServletContext中读取数据
String nums = (String) this.getServletContext()
.getAttribute("nums");
// 把数据存到文本中
buffer.write(nums);

buffer.close();
fileReader.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {

}
}

/**
* Initialization of the servlet. <br>
*
* @throws 初始化会先调用这个函数
*/
public void init() throws ServletException {
System.out.println("第一次调用");
String FilePath = this.getServletContext().getRealPath("Nums.text");

try {
FileReader fileReader = new FileReader(FilePath);
BufferedReader buffer = new BufferedReader(fileReader);
String num = buffer.readLine();
// 把数据存到ServletContext中
this.getServletContext().setAttribute("nums", num);
System.out.println("num=" + num);
buffer.close();
fileReader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {

}
}

}

我用了Runnable的线程接口
public class InitServlet extends HttpServlet implements Runnable{ }
在 public void init() throws ServletException {}方法中增加了:
InitServlet tmp = new InitServlet();
Thread al = new Thread(tmp);
al.start();

在Run中增加了以下代码,测试吗,就5秒钟保存一次结果
  public void run() {
int u = 0;
while (true) {
u++;
try {
Thread.sleep(5000);
System.out.println("你运行了"+u+"次");
this.Thread_Init();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

运行结果是它只运行一次,就不动了,也不报错,估计是取不到ServletContext()中的值




怎么办呢?新建一个线程类,它又取不到ServletContext,用构造函数传过来,也麻烦,突然间,我想到了内部类,用内部类是不是,可以解决呢,试一下再说:
public void init() throws ServletException {
System.out.println("第一次调用");
String FilePath = this.getServletContext().getRealPath("Nums.text");

try {
FileReader fileReader = new FileReader(FilePath);
BufferedReader buffer = new BufferedReader(fileReader);
String num = buffer.readLine();
this.getServletContext().setAttribute("nums", num);
System.out.println("num=" + num);
buffer.close();
fileReader.close();

class Al extends Thread{
public void run() {
int u = 0;
while (true) {
synchronized (this) {
u++;
try {
System.out.println("第" + u + "秒");
Thread.sleep(5000);
Thread_Init();
} catch (Exception e) {
e.printStackTrace();
}

}

}
}
}

Al thread = new Al();
thread.start();


} catch (Exception e) {
e.printStackTrace();
} finally {

}
}

运行一下,果然可以
信息: Server startup in 3218 ms
thread调用
第2秒
thread调用
第3秒
thread调用
第4秒
thread调用
第5秒
id= 1 password= 123
++++++++++++++++++++++
thread调用
第6秒
thread调用
第7秒
id= 1 password= 123
++++++++++++++++++++++
thread调用
第8秒

再登陆几次



现在是登陆了5次



强制关掉服务器(这样它没有机会调用destroy方法了),果然把访问量保存到文本中了




重启浏览器,再登录,果然是6次



如果你用Tomcat 6.0版本,还是会出问题,原因就是当你正常关掉服务器时,线程还在运行,这样,线程就取不到ServletContext的值,
Tomcat 7.0的版本我测试过没有这种问题,所以最好加上这句,就是主线程结束,后台线程也结束,就什么问题都没有了(想了好久才想到这个方法)
                Al thread = new Al();
thread.setDaemon(true);  //后台线程
thread.start();
这样,线程就可以每隔一段时间,自动保存访问量了,解决自己的难题,真的很开心啊 


  • 大小: 10.9 KB
  • 大小: 46.1 KB
  • 大小: 57.2 KB
  • 大小: 6.7 KB
  • 大小: 42.9 KB
  • 查看图片附件
发表评论
用户名: 匿名