java 引用类型及运用_ThreadLocal及Java引用类型

一、引用类型

1、强引用(Strong Reference)

一般用到最多的是强引用

2、软引用(Soft Reference)

如果一个对象没有强引用,只有软引用,当JVM发现内存不够时,垃圾回收器便会回收这些对象

3、弱引用(Weak Reference)

如果一个对象只有弱引用时,每次垃圾回收都会被回收

4、幻影引用(Phantom Reference)

如果一个对象仅持有幻影引用,那么它就和没有引用指向它一样,在任何时候该对象都可能被垃圾回收器回收。

幻影引用与软引用和弱引用的区别在于幻影引用必须和引用队列ReferenceQueue一起使用,幻影引用可以用来跟踪对象被回收的活动,因为当垃圾回收器准备回收一个对象的时候,如果发现它还有幻影引用,就会在回收之前,把这个幻影引用加入到与之关联的引用队列中去。

这样,程序通过判断引用队列中是否已经加入了幻影引用,来了解被引用对象是否将要被垃圾回收器回收,如果发现某个幻影引用已经被加入到引用队列,那么就可以在引用对象被回收之前采取必要的行动。

二、ThreadLocal

1、简介

ThreadLocal使用了弱引用,在一定程度上可以防止内存泄露。

2、ThreadLocal.ThreadLocalMap

此map使用的key是经过WeakReference包装的ThreadLocal对象,如果ThreadLocal对象没有其他强引用和弱引用指向时,线程也不会继续持有ThreadLocal对象,根据JVM规范,它会被垃圾回收器在下次回收时被销毁,这在一定程度避免了内存泄露。

/**

* ThreadLocalMap is a customized hash map suitable only for

* maintaining thread local values. No operations are exported

* outside of the ThreadLocal class. The class is package private to

* allow declaration of fields in class Thread.  To help deal with

* very large and long-lived usages, the hash table entries use

* WeakReferences for keys. However, since reference queues are not

* used, stale entries are guaranteed to be removed only when

* the table starts running out of space.

*/

static class ThreadLocalMap {

/**

* The entries in this hash map extend WeakReference, using

* its main ref field as the key (which is always a

* ThreadLocal object).  Note that null keys (i.e. entry.get()

* == null) mean that the key is no longer referenced, so the

* entry can be expunged from table.  Such entries are referred to

* as "stale entries" in the code that follows.

*/

static class Entry extends WeakReference {

/** The value associated with this ThreadLocal. */

Object value;

Entry(ThreadLocal k, Object v) {

super(k);

value = v;

}

}

最好使用remove方法,自己显示释放内存。

三、ThreadLocal应用

(1)ThreadCache

/**

* 利用thread local 存取servlet

* 每次request的通用数据

* @author caibosi

* @created 2014-04-01

*/

public class ThreadCache {

private static final ThreadLocal cache = new ThreadLocal(){

@Override

protected AppThreadContext initialValue() {

return new AppThreadContext();

}

};

private static class AppThreadContext{

String ip;

String userName;

Integer userId;

long startTime;

String hostName;

String logId;

Map extraData = new ConcurrentHashMap();

}

public static void setIp(String ip){

cache.get().ip = ip;

}

public static String getIp(){

return cache.get().ip;

}

public static void setUserName(String userName){

cache.get().userName = userName;

}

public static String getUserName(){

return cache.get().userName;

}

public static void setUserId(Integer userId){

cache.get().userId = userId;

}

public static Integer getUserId(){

return cache.get().userId;

}

public static void setUser(Integer userId,String userName){

cache.get().userId = userId;

cache.get().userName = userName;

}

public static void setExtraData(String key, Object data) {

cache.get().extraData.put(key, data);

}

public static Object getExtraData(String key) {

return cache.get().extraData.get(key);

}

public static void setStartTime(){

cache.get().startTime = System.currentTimeMillis();

}

public static long getStartTime(){

return cache.get().startTime;

}

public static void setLogId(){

String logId = UUID.randomUUID().toString();

cache.get().logId = logId;

}

public static String getLogId(){

return cache.get().logId;

}

public static void setHostName(String hostName){

cache.get().hostName = hostName;

}

public static String getHostName(){

return cache.get().hostName;

}

public static void release() {

cache.remove();

}

}

使用及释放:

/**

* @author caibosi

* @created 2014-04-01

*/

public class AclInterceptor extends HandlerInterceptorAdapter {

private static final Logger logger = LoggerFactory.getLogger(AclInterceptor.class);

@Resource

private AntPathMatcher antPathMatcher;

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

//记录每次访问的时间

ThreadCache.setStartTime();

//记录host

String hostname = null;

try {

hostname = InetAddress.getLocalHost().getHostName();

} catch (UnknownHostException e) {

logger.error(e.getMessage(), e);

}

if (hostname == null) {

hostname = "";

}

ThreadCache.setHostName(hostname);

//url处理

String uri = request.getRequestURI();

// 静态资源不处理

if ("/favicon.ico".equals(uri)

|| antPathMatcher.match("/static/**", uri)) {

return super.preHandle(request, response, handler);

}

request.setAttribute("_uri", uri);

// 获取登录用户的ID和用户名信息

//sso或者登录跳转

//debug mode

if(ConfigTool.isDebugEnv()){

ThreadCache.setUserId(ConfigTool.getDebugUserId());

}

//进行权限校验

boolean hasUrlAccess = true;

if(hasUrlAccess == false){

throw new AccessDeniedException("没有访问权限");

}

return super.preHandle(request,response,handler);

}

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

super.postHandle(request, response, handler, modelAndView);

String uri = request.getRequestURI().replaceAll(";.*", "");

if (uri.endsWith(".ajax") && (uri.indexOf('.') != -1 || uri.indexOf("/cron/") != -1)) {

return;

}

long time = ThreadCache.getStartTime();

if (time > 0) {

long timeCost = System.currentTimeMillis() - time;

logger.info("time used," + request.getRequestURI() + ",logId:" + ThreadCache.getLogId()

+ "," + timeCost + "ms");

request.setAttribute("_timeCost", timeCost);

}

//thread local资源释放

ThreadCache.release();

}

}

(2)事务嵌套

/**

* 封装了事务管理操作

* 主要是实现了事务嵌套的管理

* @author caibosi

* @created 2013-10-29

*/

public class TransManager {

private final static Logger logger = LoggerFactory.getLogger(TransManager.class);

private final static ThreadLocal transLocal = new ThreadLocal();

/**

* 设置事务的隔离级别

* @param level

*/

public static void setTransactionViolation(TransactionLevel level){

Transaction tran = transLocal.get();

Connection conn = tran.getConn();

try {

conn.setTransactionIsolation(level.getValue());

} catch (SQLException e) {

logger.error("setting transaction violation failed",e);

throw new RuntimeException("setting transaction violation failed",e);

}

}

/**

* 开启事务

*/

public static void openTransaction(TransactionLevel level){

Transaction tran = transLocal.get();

if(tran==null){

tran = new Transaction();

Connection conn = DBManager.getConnection();

try {

conn.setAutoCommit(false);

if(level!=null && level.getValue()!= TransactionLevel.getDefault().getValue()){

conn.setTransactionIsolation(level.getValue());

}

} catch (SQLException e) {

logger.error("open transaction error",e);

throw new RuntimeException("open transaction error");

}

tran.setConn(conn);

tran.setCommitCount(0);

tran.setOpenCount(1);

tran.setCurrentCount(1);

transLocal.set(tran);

} else{

tran.setOpenCount(tran.getOpenCount()+1);

tran.setCurrentCount(tran.getCurrentCount()+1);

}

}

/**

* 提交事务

*/

public static void commitTransaction(){

Transaction tran = transLocal.get();

if(tran == null)

throw new RuntimeException("commit transaction , transaction null");

//判断要不要真正提交

if(tran.getCurrentCount()>1){

tran.setCommitCount(tran.getCommitCount() + 1);

tran.setCurrentCount(tran.getCurrentCount()-1);

return;

}

Connection conn = tran.getConn();

if(tran.canReallyCommit()){

try {

conn.commit();

} catch (SQLException e) {

logger.error("commit transaction error",e);

throw new RuntimeException("commit transaction error");

}

}

}

/**

* 回滚事务

* 这里不真正回滚

* 做个标记

* 在close的时候判断是否要回滚

*/

public static void rollbackTransaction(){

Transaction tran = transLocal.get();

//        if(tran == null){

//            logger.info("rollback trans null");

//            return;

//        }

tran.setCommitCount(0);

}

/**

* 终止事务

*/

public static void closeTransaction(){

Transaction tran = transLocal.get();

//        if(tran == null){

//            logger.info("close trans null");

//            return;

//        }

//如果当前还有1个以上的事务,不能真正关闭事务

if(tran.getCurrentCount()>1){

tran.setCommitCount(tran.getCurrentCount()-1);

return;

}

//如果只剩一个事务,则真正结束事务,清理变量

Connection conn = tran.getConn();

if(tran.canReallyCommit()==false){

try {

conn.rollback();

logger.info("#### rollback transaction");

} catch (SQLException e) {

logger.error("rollback transaction failed",e);

}finally{

transLocal.remove();

try {

conn.close();

} catch (SQLException e) {

logger.error("close conn failed",e);

throw new RuntimeException("close conn failed",e);

}

}

}

}

}

/**

* 封装了connection

* 事务提交次数

* 事务嵌套层次

* 事务开启次数

* 用于控制事务嵌套

* @author caibosi

* @created 2013-10-29

*/

class Transaction {

private Connection conn;

/**

* 统计事务次数

* 每开启一次,增加一次

* 用来与commitCount来判断

* 事务是否全部提交

*/

private int openCount;

/**

* 提交次数

* 每提交一次,增加一次

*/

private int commitCount;

/**

*  当前的事务数

*  开启一次增加1

*  提交一次减去1

*/

private int currentCount;

/**

* 判断是否能够真正提交事务

* @return

*/

boolean canReallyCommit(){

return commitCount+1 == openCount;

}

Connection getConn() {

return conn;

}

void setConn(Connection conn) {

this.conn = conn;

}

int getCommitCount() {

return commitCount;

}

void setCommitCount(int commitCount) {

this.commitCount = commitCount;

}

int getOpenCount() {

return openCount;

}

void setOpenCount(int openCount) {

this.openCount = openCount;

}

int getCurrentCount() {

return currentCount;

}

void setCurrentCount(int currentCount) {

this.currentCount = currentCount;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值