java.util.concurrent.atomic 包中包括了原子变量( atomic variable )类,这些类用来实现数字和对象引用的原子状态的转换,把long类型的计数器替换成AtomicLong类型的,我们可以确保所有访问计数器状态的操作都是原子的,计数器是线程安全的了,而计数器的状态就是servlet的状态,所以我们的servlet再次车归纳为线程安全的了。
使用java.util.concurrent包中支持多线程的数据结构类(如:ConcurrentHashMap等),对写多线程JAVA程序带来很多方便.其中:java.util.concurrent.atomic包是提供原子操作的基本类.如:AtomicLong类.为了提高性能,AtomicLong等类在实现同步时,没有用synchronized关键字,而是直接使用了最低层(本地c语言实现代码)来完成的,因而你是看不到用synchronized关键字的.
比如:AtomicLong类中原子操作方法:
public final boolean compareAndSet(long expect, long update) ;
就是直接使用SUN公司低层本地代码的原子方法(native方法):
public final native boolean compareAndSwapLong(...)
来实现的.
如下面的Servlet的非安全线程的:
package com.etrip.web;
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;
/**
* Servlet implementation class CountServlets
*/
public class CountServlets extends HttpServlet {
private static final long serialVersionUID = 1L;
//记录访问此Servlet的数量
private static long count=0;
/**
* @see HttpServlet#HttpServlet()
*/
public CountServlets() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw=response.getWriter();
count++;
pw.print("当前的请求次数为为:"+count);
pw.flush();
pw.close();
}
}
利用像AtomicLong这样已有的线程安全对象管理类的状态是非常实用的,相对于非线程安全对象,判断一个线程安全对象的可能状态和状态的转换要容易的多了,这简化了维护和验证 线程安全性的工作。
package com.etrip.web;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.atomic.*;
/**
*
*
*
*/
public class CountExtServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//记录访问此Servlet的数量
private final AtomicLong count=new AtomicLong(0);
/**
* @see HttpServlet#HttpServlet()
*/
public CountExtServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw=response.getWriter();
count.incrementAndGet();
pw.print("当前的请求次数为为:"+count.get());
pw.flush();
pw.close();
}
}
Java中提供的原子操作类
AtomicInteger,AtomicBoolean,AtomicLong,AtomicReference等。这是由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。
为了确保线程的全权,“检查再运行”操作(如惰性初始化)和读改写操作(如自增)必须是原子操作。
我们将“检查再运行” 和读改写操作的全部执行过程看作是符合操作。为了保证线程安全,操作必须原子
地执行。