java 线程---成员变量与局部变量
2012-03-19 15:04
309 查看
关于成员变量与局部变量:如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,他们对该成员变量是彼此影响的(也就是说一个线程对成
员变量的改变会影响到另一个线程) 。 如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝,一个线程对该局部变量的改变不会影响到其他的线程。
实例:
Servlet容器为了响应多个用户同时访问一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet的service()方法。此时可能发生多线程对同一数据进行访问的情况。
Java代码
public class Hello extends HttpServlet{
private String name;
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
response.setContentType("text/html;charset=UTF-8");
name = (String)request.getParameter("name"); //接收参数
PrintWriter out = response.getWriter();
out.println("<html><head><title>test</title></head><body>");
out.println("你好"+name);
out.println("</body></html>");
out.close();
}
}
如果多线程并发访问,会访问同一个实例变量,则会共用name,而出现用户得到数据不一致的现象。
解决办法:
1.将name设置为局部变量。
Java代码
public class Hello extends HttpServlet{
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
response.setContentType("text/html;charset=UTF-8");
String name = (String)request.getParameter("name"); //接收参数
...
}
}
每当一个线程执行doPost()时,在线程的堆栈中就会创建name这个局部变量,当线程执行完该方法,局部变量就结束生命周期。如果多个线程同时执行该方法,那么每个线程都拥有自己的局部变量。
2.使用Java同步机制对多线程同步
Java代码
public class Hello extends HttpServlet{
private String name;
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
response.setContentType("text/html;charset=UTF-8");
synchronized(this){
name = (String)request.getParameter("name"); //接收参数
...
}
...
}
}
这样可确保在任意一时刻,只允许有一个工作线程执行doPost()中的同步代码块。只有当这个工作线程退出同步代码块时,其他工作线程才允许执行同步代码块。这使得任意时刻不会有两个线程同时操纵同一个实例变量,从而避免并发问题。
3.实现被废弃的SingleThreadModel接口
public class Hello extends HttpServlet implements SingleThreadModel{
...
}
如果实现此接口,则Servlet容器实现可以采用以下两种方式之一来运行Servlet:
1)在任意一时刻,只允许有一个工作线程执行Servlet的service()方法。如果有多个用户同时请求访问该Servlet,那么这些客户请求被放入等待队列,容器会依次响应等待队列中的每个客户请求。这种实现方式实际上禁止了多个客户端对同一个Servlet的并发访问。
2)Servlet容器为每个Servlet创建一个对象池,在这个池中存放了同一个Servlet类的多个实例。如果有多个用户同时请求访问该Servlet,Servlet容器会为每个请求分配一个工作线程,并且从对象池中取出一个空闲的Servlet实例,把它分配给工作线程。每个工作线程执行自己的Servlet实例的service()方法。这种实现方式表面上允许客户端对同一个Servlet并发访问,但实际上不同客户端访问的是同一个Servlet类的不同实例。
如果实例变量需要共享,用以进行计算,这种方法并不能有效的避免并发问题。
员变量的改变会影响到另一个线程) 。 如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝,一个线程对该局部变量的改变不会影响到其他的线程。
实例:
Servlet容器为了响应多个用户同时访问一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet的service()方法。此时可能发生多线程对同一数据进行访问的情况。
Java代码
public class Hello extends HttpServlet{
private String name;
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
response.setContentType("text/html;charset=UTF-8");
name = (String)request.getParameter("name"); //接收参数
PrintWriter out = response.getWriter();
out.println("<html><head><title>test</title></head><body>");
out.println("你好"+name);
out.println("</body></html>");
out.close();
}
}
如果多线程并发访问,会访问同一个实例变量,则会共用name,而出现用户得到数据不一致的现象。
解决办法:
1.将name设置为局部变量。
Java代码
public class Hello extends HttpServlet{
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
response.setContentType("text/html;charset=UTF-8");
String name = (String)request.getParameter("name"); //接收参数
...
}
}
每当一个线程执行doPost()时,在线程的堆栈中就会创建name这个局部变量,当线程执行完该方法,局部变量就结束生命周期。如果多个线程同时执行该方法,那么每个线程都拥有自己的局部变量。
2.使用Java同步机制对多线程同步
Java代码
public class Hello extends HttpServlet{
private String name;
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,java.io.IOException{
response.setContentType("text/html;charset=UTF-8");
synchronized(this){
name = (String)request.getParameter("name"); //接收参数
...
}
...
}
}
这样可确保在任意一时刻,只允许有一个工作线程执行doPost()中的同步代码块。只有当这个工作线程退出同步代码块时,其他工作线程才允许执行同步代码块。这使得任意时刻不会有两个线程同时操纵同一个实例变量,从而避免并发问题。
3.实现被废弃的SingleThreadModel接口
public class Hello extends HttpServlet implements SingleThreadModel{
...
}
如果实现此接口,则Servlet容器实现可以采用以下两种方式之一来运行Servlet:
1)在任意一时刻,只允许有一个工作线程执行Servlet的service()方法。如果有多个用户同时请求访问该Servlet,那么这些客户请求被放入等待队列,容器会依次响应等待队列中的每个客户请求。这种实现方式实际上禁止了多个客户端对同一个Servlet的并发访问。
2)Servlet容器为每个Servlet创建一个对象池,在这个池中存放了同一个Servlet类的多个实例。如果有多个用户同时请求访问该Servlet,Servlet容器会为每个请求分配一个工作线程,并且从对象池中取出一个空闲的Servlet实例,把它分配给工作线程。每个工作线程执行自己的Servlet实例的service()方法。这种实现方式表面上允许客户端对同一个Servlet并发访问,但实际上不同客户端访问的是同一个Servlet类的不同实例。
如果实例变量需要共享,用以进行计算,这种方法并不能有效的避免并发问题。
相关文章推荐
- java 线程---成员变量与局部变量
- java线程安全问题之静态成员变量、实例成员变量、局部变量
- java线程安全问题之静态成员变量、实例成员变量、局部变量
- java 线程---成员变量与局部变量
- java线程安全问题之静态成员变量、实例成员变量、局部变量
- java线程安全问题之静态成员变量、实例成员变量、局部变量
- java 线程---成员变量与局部变量
- 局部变量与成员变量的区别 及堆java中堆与栈的分析
- Java成员变量与局部变量的区别
- java中成员变量、局部变量、静态变量的区别
- java基础之成员变量与局部变量
- 虚拟机大牛RednaxelaFX关于java里面的静态变量、成员变量、局部变量的内存分配
- java学习笔记之成员变量和局部变量的区别
- java 成员变量与局部变量有什么区别
- java 中的 成员变量、局部变量、静态变量、类变量、非静态变量、实例变量、向前引用、非法向前引用、静态代码块、非静态代码块 执行时机
- java学习--类变量、成员变量、局部变量
- I学霸官方免费教程九:Java基础之成员变量(全局变量)和局部变量
- [Java入门笔记] 面向对象编程基础(三):成员变量和局部变量
- java基础-成员变量与局部变量的联系与区别
- Java中成员变量和局部变量的区别