java对象,直接new,用静态变量返回static块中new好的对象,用synchronized返回静态变量,三者区别详解
举三个例子说明一下:第一个例子publicclassQueryCouponAmountDao{publicQueryCouponAmountDao(){}publicvo...
举三个例子说明一下:
第一个例子
public class QueryCouponAmountDao {
public QueryCouponAmountDao() {
}
public void run(){}
}
public class QueryCouponAmountService {
public QueryCouponAmountService() {
}
public void process(){
QueryCouponAmountDao query=new QueryCouponAmountDao();
query.run();
}
}
第二个例子
public class QueryCouponAmountDao {
private QueryCouponAmountDao() {
}
public static QueryCouponAmountDao instance;
static {
instance = new QueryCouponAmountDao();
}
public void run(){}
}
public class QueryCouponAmountService {
private QueryCouponAmountService() {
}
public static QueryCouponAmountService instance;
static {
instance = new QueryCouponAmountService();
}
public void process(){
QueryCouponAmountDao query=QueryCouponAmountDao.instance;
query.run();
}
}
第三个例子
public class QueryCouponAmountDao {
private QueryCouponAmountDao() {
}
private static QueryCouponAmountDao instance;
public synchronized static QueryCouponAmountDao getIntance() {
if (null == instance) {
instance = new QueryCouponAmountDao();
}
return instance;
}
public void run(){}
}
public class QueryCouponAmountService {
private QueryCouponAmountService() {
}
private static QueryCouponAmountService instance;
public synchronized static QueryCouponAmountService getIntance() {
if (null == instance) {
instance = new QueryCouponAmountService();
}
return instance;
}
public void process(){
QueryCouponAmountDao query=QueryCouponAmountDao.getIntance();
query.run();
}
}
类实例的方式当然都懂的,怪我说的不仔细,我是想问,这几种实现方式,在实际使用中的区别,比如我一口气取100w个实例,在三者情况下jvm处理的时所花费的时间和空间的比较,当然我知道,100W次new和一个static变量得100W次,空间上肯定是不一样的,但是其他方面呢?还有多线程环境下,又是怎么玩的?另外,new是每次都是取一个新的没什么疑问,如果是第二种情况,每次都是取类加载时的那一个静态实例对象,那这个类中的实例变量,静态变量不是都是共享的了,也就是说如果我第一次取这个类,改变了其中的实例变量和静态变量,那么我第二次再取这个静态实例对象象的时候,不是能够读取到前一个的改动了么?这样跟new出来的初始化时不一样的。第二和第三种情况在多线程环境下除了一个直接得对象,一个加锁得对象,当然实例的时间也有区别的,除了这些还有什么其他区别?@青衣秀士
上述问题自己有些明白,但是也有些说不清楚,望高手指导 展开
第一个例子
public class QueryCouponAmountDao {
public QueryCouponAmountDao() {
}
public void run(){}
}
public class QueryCouponAmountService {
public QueryCouponAmountService() {
}
public void process(){
QueryCouponAmountDao query=new QueryCouponAmountDao();
query.run();
}
}
第二个例子
public class QueryCouponAmountDao {
private QueryCouponAmountDao() {
}
public static QueryCouponAmountDao instance;
static {
instance = new QueryCouponAmountDao();
}
public void run(){}
}
public class QueryCouponAmountService {
private QueryCouponAmountService() {
}
public static QueryCouponAmountService instance;
static {
instance = new QueryCouponAmountService();
}
public void process(){
QueryCouponAmountDao query=QueryCouponAmountDao.instance;
query.run();
}
}
第三个例子
public class QueryCouponAmountDao {
private QueryCouponAmountDao() {
}
private static QueryCouponAmountDao instance;
public synchronized static QueryCouponAmountDao getIntance() {
if (null == instance) {
instance = new QueryCouponAmountDao();
}
return instance;
}
public void run(){}
}
public class QueryCouponAmountService {
private QueryCouponAmountService() {
}
private static QueryCouponAmountService instance;
public synchronized static QueryCouponAmountService getIntance() {
if (null == instance) {
instance = new QueryCouponAmountService();
}
return instance;
}
public void process(){
QueryCouponAmountDao query=QueryCouponAmountDao.getIntance();
query.run();
}
}
类实例的方式当然都懂的,怪我说的不仔细,我是想问,这几种实现方式,在实际使用中的区别,比如我一口气取100w个实例,在三者情况下jvm处理的时所花费的时间和空间的比较,当然我知道,100W次new和一个static变量得100W次,空间上肯定是不一样的,但是其他方面呢?还有多线程环境下,又是怎么玩的?另外,new是每次都是取一个新的没什么疑问,如果是第二种情况,每次都是取类加载时的那一个静态实例对象,那这个类中的实例变量,静态变量不是都是共享的了,也就是说如果我第一次取这个类,改变了其中的实例变量和静态变量,那么我第二次再取这个静态实例对象象的时候,不是能够读取到前一个的改动了么?这样跟new出来的初始化时不一样的。第二和第三种情况在多线程环境下除了一个直接得对象,一个加锁得对象,当然实例的时间也有区别的,除了这些还有什么其他区别?@青衣秀士
上述问题自己有些明白,但是也有些说不清楚,望高手指导 展开
3个回答
展开全部
首先,不管哪种方式,都是通过new进行实例化,三种方式的不同在于,每次调用使用的dao对象是否相同。
1)直接new:每次调用都需要实例化;
2)静态变量,在这个类被加载时已经实例化好,调用process方法时直接使用;
3)带synchronized的getter,与第2个基本一致,只是实例化阶段在第一次使用时,简称为lazy init,懒加载。
在类的实例数来看,第一种为多个,后两种为一个。
==================
“比如我一口气取100w个实例,在三者情况下jvm处理的时所花费的时间和空间的比较,当然我知道,100W次new和一个static变量得100W次,空间上肯定是不一样的,但是其他方面呢?还有多线程环境下,又是怎么玩的?另外,new是每次都是取一个新的没什么疑问,如果是第二种情况,每次都是取类加载时的那一个静态实例对象,那这个类中的实例变量,静态变量不是都是共享的了,也就是说如果我第一次取这个类,改变了其中的实例变量和静态变量,那么我第二次再取这个静态实例对象象的时候,不是能够读取到前一个的改动了么?这样跟new出来的初始化时不一样的。第二和第三种情况在多线程环境下除了一个直接得对象,一个加锁得对象,当然实例的时间也有区别的,除了这些还有什么其他区别?”
jvm处理时的时间和空间比较,空间上来看,每次调用都new,频繁调用后必然会触发GC,而调用GC进行回收时一般都会暂停工作线程,如果回收时间较长则会造成卡顿现象。从时间上来看,每次new时都需要去分配堆内存,而static共享的只需要取出句柄即可。
static在这个比较中的主要劣势在于:1)资源共享,多线程场景注意保护;2)资源常驻内存,很难被回收。
多线程方面,不能简单从实例数量上来看,而是需要看具体场景是否存在着资源竞争。
1)直接new:每次调用都需要实例化;
2)静态变量,在这个类被加载时已经实例化好,调用process方法时直接使用;
3)带synchronized的getter,与第2个基本一致,只是实例化阶段在第一次使用时,简称为lazy init,懒加载。
在类的实例数来看,第一种为多个,后两种为一个。
==================
“比如我一口气取100w个实例,在三者情况下jvm处理的时所花费的时间和空间的比较,当然我知道,100W次new和一个static变量得100W次,空间上肯定是不一样的,但是其他方面呢?还有多线程环境下,又是怎么玩的?另外,new是每次都是取一个新的没什么疑问,如果是第二种情况,每次都是取类加载时的那一个静态实例对象,那这个类中的实例变量,静态变量不是都是共享的了,也就是说如果我第一次取这个类,改变了其中的实例变量和静态变量,那么我第二次再取这个静态实例对象象的时候,不是能够读取到前一个的改动了么?这样跟new出来的初始化时不一样的。第二和第三种情况在多线程环境下除了一个直接得对象,一个加锁得对象,当然实例的时间也有区别的,除了这些还有什么其他区别?”
jvm处理时的时间和空间比较,空间上来看,每次调用都new,频繁调用后必然会触发GC,而调用GC进行回收时一般都会暂停工作线程,如果回收时间较长则会造成卡顿现象。从时间上来看,每次new时都需要去分配堆内存,而static共享的只需要取出句柄即可。
static在这个比较中的主要劣势在于:1)资源共享,多线程场景注意保护;2)资源常驻内存,很难被回收。
多线程方面,不能简单从实例数量上来看,而是需要看具体场景是否存在着资源竞争。
展开全部
调用楼上的话,我做部分补充。
首先,不管哪种方式,都是通过new进行实例化,三种方式的不同在于,每次调用使用的dao对象是否相同。
1)直接new:每次调用都需要实例化;
2)静态变量,在这个类被加载时已经实例化好,调用process方法时直接使用;
3)带synchronized的getter,与第2个基本一致,只是实例化阶段在第一次使用时,简称为lazy init,懒加载。在类的实例数来看,第一种为多个,后两种为一个。
补充:后两种属于一种开发模式叫单例模式,就是说实例只有一个。前者叫饿汉模式,即加载就实例化一个静态实例。后者是懒汉模式,即第一次使用的时候创建一个静态实例。加锁是为了线程安全,保证实例有且只有一个。
首先,不管哪种方式,都是通过new进行实例化,三种方式的不同在于,每次调用使用的dao对象是否相同。
1)直接new:每次调用都需要实例化;
2)静态变量,在这个类被加载时已经实例化好,调用process方法时直接使用;
3)带synchronized的getter,与第2个基本一致,只是实例化阶段在第一次使用时,简称为lazy init,懒加载。在类的实例数来看,第一种为多个,后两种为一个。
补充:后两种属于一种开发模式叫单例模式,就是说实例只有一个。前者叫饿汉模式,即加载就实例化一个静态实例。后者是懒汉模式,即第一次使用的时候创建一个静态实例。加锁是为了线程安全,保证实例有且只有一个。
更多追问追答
追问
麻烦看下补充提问呵,qqq
追答
请搞明白。第一种想要几个实例,你自己new几个。后两种都是单例,该类的实例只有一个,何来100W个实例一说?
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1)直接new:每次开辟新的内存空间,生成一个新对象,对象里的属性全部为默认值了。可以人工清除灵活使用内存空间。
2)静态变量:在程序启动后一直存在内存中,适用于常量的使用和初始化内容。
3)带synchronized:简单的说就是单例模式,可以自己去查查。在项目设计时用的比较多。长用于控制其他对象。
2)静态变量:在程序启动后一直存在内存中,适用于常量的使用和初始化内容。
3)带synchronized:简单的说就是单例模式,可以自己去查查。在项目设计时用的比较多。长用于控制其他对象。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询