美文网首页IT 森林Java 技术
Java多线程6-无状态对象

Java多线程6-无状态对象

作者: GavinBoy | 来源:发表于2017-10-17 23:29 被阅读16次

状态变量:实例变量、静态变量

如果一个类的同一个实例被多个线程共享并不会使这些线程存在共享状态,那么这个类及其任意一个实例就被称为无状态对象;反之,如果一个类的同一个实例被多个线程共享,会使这些线程存在共享状态,那么这个类及其任意一个实例就被称为有状态对象

无状态对象不包含任何实例变量,且不包含任何静态变量或者其包含的静态变量都是只读的(常量)

有状态对象分为:状态可变对象、状态不可变对象

无状态对象具有固有的线程安全性,它可以被多个线程共享,而这些线程在执行该对象的任何方法时都无须使用同步机制

即使一个类不包含任何实例变量或者静态变量,执行该类方法的多个线程也仍然可能存在共享状态;因为类方法中可能存在的实例对象中包含有静态变量或实例变量。此时就需要在方法中加锁来保障

托管类:实例的创建、初始化以及销毁的整个生命周期完全由别人控制

不可变对象:一经创建其状态就保持不变的对象,其具有固有的线程安全性,所以也可以像无状态对象那样被多个线程共享

一个严格意义上的不可变对象要同时满足以下所有条件:

a、类本身使用final来修饰:为防止通过创建子类来改变其定义的行为

b、所有字段都是用final修饰:被修饰的字段值不可变,保证初始化安全,对其他线程可见时,它必定是初始化完成的

c、对象在此初始化过程中没有逸出(Escape):防止其他类(如该类的内部匿名类)在对象初始化过程中修改其状态

d、任何字段,若引用了其他状态可变的对象(集合、数组等),则这些字段必须是private修饰的,若有相关方法要返回这些字段值,则应该进行防御性复制

线程特有对象

一个实例只能被一个线程访问的对象就被称为线程特有对象,相应的线程就被称为特有对象的持有线程 

优点:保障对非线程安全对象的访问的线程安全,又避免了锁的开销,有利于减少对象的创建次数

ThreadLocal相当于线程访问其线程特有对象的代理,即各个线程通过这个对象可以创建并访问各自线程特有对象,T指定了相应线程特有对象的类型

其多个线程间与ThreadLocal实例间的访问关系:

ThreadLocal有四个常用方法:get()、set(T value)、initialValue()、remove()InitialValue()方法的返回值成为当前线程的线程特有对象ThreadLocal实现线程安全示例代码:public class ThreadManager extends HttpServlet{final static ThreadLocalSDF = new ThreadLocal(){

@Override

protected SimpleDateFormat initialValue(){

return new SimpleDateFormat("yyyy-MM-dd");

}

};

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException {

final SimpleDateFormat sdf = SDF.get();

String strExpiryDate = req.getParameter("expirtyDate");

try(PrintWriter pwr = resp.getWriter()){

sdf.parse(strExpiryDate);

} catch(ParseException e) {

e.printStackTrace();

}

}

}

线程局部变量通常是会被声明为某个类的静态变量;ThreadLocal实例通常会被作为某个类的静态字段使用

线程持有对象可能导致的问题及其规避:

a、 退化与数据错乱

b、 ThreadLocal可能内存泄露、伪内存泄露

线程与ThreadLocal、线程特有对象的引用关系

每个Thread实例内部会维护一个类似HashMap的对象:ThreadLocalMap; 每个ThreadLocalMap内部包含若干个Entry(条目,一个键Key,值Value) key是一个ThreadLocal实例,value是一个线程持有对象;Entry可被复用。

由于ThreadLocal可能导致内存泄露,伪内存泄露;需要清理Entry所属线程特有对象,通过在当前线程中调用ThreadLocal.remove()。

线程特有对象的典型应用场景

a、 需要使用非线程安全对象,但又不希望因此而引入锁

b、 使用线程安全对象,但希望避免其使用锁的开销和相关问题

c、 隐式参数传递

d、 特定于线程的单例模式

相关文章

  • Java多线程6-无状态对象

    状态变量:实例变量、静态变量 如果一个类的同一个实例被多个线程共享并不会使这些线程存在共享状态,那么这个类及其任意...

  • 第35节:Java面向对象中的多线程

    Java面向对象中的多线程 多线程 在Java面向对象中的多线程中,要理解多线程的知识点,首先要掌握什么是进程,什...

  • Android多线程-并发实例记录

    多线程基本概念 Java线程五种基本状态:1)新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thr...

  • Java面试题

    Java面试 Java、框架、JVM Java 基础、容器、多线程、反射、对象拷贝、Java web模块、异常模块...

  • 带你搞懂Java多线程(三)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二) 什么是线程间的共享 Java支持多个线程同时访问一个对象...

  • Java的基本概念-1

    JAVA介绍 面向对象程序和java平台总称不使用指针,使用引用支持多线程 Java基础语法 对象:类的实例,分为...

  • Java并发编程(二)同步

    如果你的java基础较弱,或者不大了解java多线程请先看这篇文章java多线程(一)线程定义、状态和属性 同步一...

  • java文艺复兴

    JAVA 语言基础 理解面向对象OO 常用类 集合 IO 多线程 GUI(??) 网络编程 JAVA WEB (...

  • Java多线程之(三)线程的生命周期

    JDK中用Thread.State类定义了线程的五种状态 要想实现多线程,必须在主线程中创建新的线程对象。Java...

  • JAVA多线程及线程状态转换

    Java多线程及线程状态转换 - 祖华 - 博客园

网友评论

    本文标题:Java多线程6-无状态对象

    本文链接:https://www.haomeiwen.com/subject/trnjuxtx.html