java 无状态和有状态区别
诸位Java程序员,想必大家对SimpleDateFormat并不陌生。不过,你是否知道,SimpleDateFormat不是线程安全的(thread safe)。这意味着,下面的代码是错误的:
class Sample {
private static final DateFormat format = new SimpleDateFormat("yyyy.MM.dd"); public String getCurrentDateText() {
return format.format(new Date());
}
}
从功能的角度上看,单独执行这段代码是没有问题的,但放到多线程环境下,因为SimpleDateFormat不是线程安全的,这段代码就会出错。所以,要想让这段代码正确,我们只要稍做微调:
public class Sample {
public String getCurrentDateText() {
return new SimpleDateFormat("yyyy.MM.dd").format(new Date());
}
}
不知你是否注意到,这里的调整只是由原来的共享format这个变量,变成了每次调用这个方法时创建出一个新的SimpleDateFormat变量。
作为一个专业程序员,我们当然知道,相比于共享一个变量的开销要比每次创建小。之所以我们必须这么做,是因为SimpleDateFormat不是线程安全的。但从SimpleDateFormat提供给我们的接口上来看,实在让人看不出它与线程安全有和相干。那接下来,我们就要打开JDK的源码,看一下其中的代码之丑。
如果你手头没有JDK的源码,这里是个不错的参考。
在format方法里,有这样一段代码:
calendar.setTime(date);
其中,calendar是DateFormat的protected字段。这条语句改变了calendar,稍后,calendar还会用到(在subFormat方法里),而这就是引发问题的根源。
想象一下,在一个多线程环境下,有两个线程持有了同一个SimpleDateFormat的实例,分别调用format方法:
线程1调用format方法,改变了calendar这个字段。
中断来了。
线程2开始执行,它也改变了calendar。
又中断了。
线程1回来了,此时,calendar已然不是它所设的值,而是走上了线程2设计的道路。
BANG!!! 稍微花点时间分析一下format的实现,我们便不难发现,用到calendar,唯一的好处,就是在调用subFormat时,少了一个参数,却带来了这许多的问题。其实,只要在这里用一个局部变量,一路传递下去,所有问题都将迎刃而解。
这个问题背后隐藏着一个更为重要的问题:无状态。
无状态方法的好处之一,就是它在各种环境下,都可以安全的调用。衡量一个方法是否是有状态的,就看它是否改动了其它的东西,比如全局变量,比如实例的字段。format方法在运行过程中改动了SimpleDateFormat的calendar字段,所以,它是有状态的。
写程序,我们要尽量编写无状态方法。
------------------------------------------------------------------------------------------------------------------
有状态:
Java对象的状态用属性来表示,有属性,也就是对象的变量,就表示是有状态的,有状态就是线程不安全的。
关于线程安全:
1) 常量始终是线程安全的,因为只存在读操作。
2)每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
3)局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
java 无状态和有状态区别的更多相关文章
- OID,主键生成策略,PO VO DTO,get和load区别,脏检查,快照,java对象的三种状态
主键生成策略 sequence 数据库端 native 数据库端 uuid 程序端 自动赋值 生成的是一个32位的16进制数 实体类需把ID改成String 类型 assigned 程序端 需手 ...
- hibernate中的java对象有几种状态,其相互关系如何(区别和相互转换)。
hibernate中的java对象有几种状态,其相互关系如何(区别和相互转换). 解答:在Hibernate中,对象有三种状态:临时状态.持久状态和游离状态. 临时状态:当new一个实体对象后,这个对 ...
- 线程、进程的区别,Java的几个线程状态
线程.进程的区别 进程的定义:进程就是程序在一个数据集合上的一次执行过程.他与程序的区别在于程序是静态的代码,而进程是动态的执行过程. 进程的特性:1.结构性,进程由程序块.数据块.进程 ...
- java 线程的几种状态
java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在正常 ...
- http协议无状态中的 "状态" 到底指的是什么?!
引子: 最近在好好了解http,发现对介绍http的第一句话[http协议是无状态的,无连接的]就无法理解了:无状态的[状态]到底指的是什么?! 找了很多资料不仅没有发现有一针见血正面回答这个问题的, ...
- Java线程状态Jstack线程状态BLOCKED/TIMED_WAITING/WAITING解释
一.线程5种状态 新建状态(New) 新创建了一个线程对象. 就绪状态(Runnable) 线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获 ...
- Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)
线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...
- 设计模式《JAVA与模式》之状态模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述状态(State)模式的: 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为 ...
- 【转】java 线程的几种状态
java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在正常 ...
- Java线程基础知识(状态、共享与协作)
1.基础概念 CPU核心数和线程数的关系 核心数:线程数=1:1 ;使用了超线程技术后---> 1:2 CPU时间片轮转机制 又称RR调度,会导致上下文切换 什么是进程和线程 进程:程序运行资源 ...
随机推荐
- [CF468D]Tree
[CF468D]Tree 题目大意: 一棵\(n(n\le10^5)\)个编号为\(1\sim n\)的点的带边权的树,求一个排列\(p_{1\sim n}\),使\(\sum dis(i,p_i ...
- hadoop map(分片)数量确定
之前学习hadoop的时候,一直希望可以调试hadoop源码,可是一直没找到有效的方法,今天在调试矩阵乘法的时候发现了调试的方法,所以在这里记录下来. 1)事情的起因是想在一个Job里设置map的数量 ...
- UTF8、UTF16、UTF16-LE、UTF16-BE、UTF32都是些什么?
下述内容大部分引用自CSDN: Unicode 是 unicode.org 制定的编码标准,目前得到了绝大部分操作系统和编程语言的支持.unicode.org 官方对 Unicode 的定义是:Uni ...
- HTML-DEV-ToolLink(常用的在线字符串编解码、代码压缩、美化、JSON格式化、正则表达式、时间转换工具、二维码生成与解码等工具,支持在线搜索和Chrome插件。)
HTML-DEV-ToolLink:https://github.com/easonjim/HTML-DEV-ToolLink 常用的在线字符串编解码.代码压缩.美化.JSON格式化.正则表达式.时间 ...
- 我的vim配置---jeffy-vim-v2.1.tar
http://files.cnblogs.com/pengdonglin137/jeffy-vim-v2.1.rar 使用方法: 在Linux下,解压后,进入解压后的目录,执行./install.sh ...
- 在Windows平台下安装与配置Memcached及C#使用方法
1.在Windows下安装Memcached 资料来源:http://www.jb51.net/article/30334.htm 在Windows平台下安装与配置Memcached的方法,Memca ...
- 构建高性能web站点-1
以下为阅读<构建高性能web站点>郭欣 著 这本书的适合读者: 1.编写web程序.关心站点性能,并且希望自己做的更加出色的开发人员 2.关心性能和可用性的web架构师 3.希望构建高性能 ...
- c# word 操作
public class WordOperate { #region 新建Word文档 /// <summary> /// 动态生成Word文档并填充内容 /// </summary ...
- 记录一个奇妙的Bug, -1 >= 2 ?
直接上代码: #include <iostream> #include <vector> using namespace std; int main() { vector< ...
- 关于部分Android手机安装apk,无法获取正常的logo
最近出现过类似的问题,主要出现是在,MediaPad X1 7.0和MediaPad M1 8.0. 发布应用的时候明明配置好了图标的,但是始终找不到原因,郁闷了好几个小时,也浪费了好几个小时. 如果 ...