`
xiaozhi7616
  • 浏览: 191590 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

面试题:线程安全的单例模式

    博客分类:
  • Java
阅读更多

面试被问到一个线程安全的单例模式问题,想拿出来讨论一下,

我通常会使用的这样的写法来实现单例:

 

public class Singleton {
	
	private Singleton() {}
	private static Singleton instance = null;

	public static Singleton getInstance() {
		if(instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

 

单例的目的是为了保证运行时Singleton类只有唯一的一个实例,最常用的地方比如拿到数据库的连接,Spring的中创建BeanFactory这些开销比较大的操作,而这些操作都是调用他们的方法来执行某个特定的动作。


面试官的问题是:单例会带来什么问题?


我第一反映就是如果多个线程同时调用这个实例,会有线程安全的问题,当时就这么说了,然后他问:“怎么实现一个线程安全的单例模式呢?”


这个问题我没有回答上来,当时脑子里闪了一下如果用synchronized来锁定可能会有一些问题,至于是什么问题没有想明白,就选择没有回答。


这里请问各位高手,

1、如果不执行修改对象的操作的情况下,单单执行一个读取操作,还有没有进行同步的必要?

2、保证单例的线程安全使用synchronized会产生什么样的问题?

3、不使用synchronized,有什么方式来保证线程安全?

4、假如下次再面试遇到这种情形,用什么方式回答会使面试官感到比较满意?

 

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

 

感谢大家的讨论与支持,总结一下:

 

实际上使用什么样的单例实现取决于不同的生产环境,懒汉式也就是我在上面举得那个例子,这种方式适合于单线程程序,多线程情况下需要保护getInstance()方法,否则可能会产生多个Singleton对象的实例。

 

在此基础上确保getInstance()方法一次只能被一个线程调用就需要在getInstance()方法之前加上 synchronized 关键字,锁定整个方法,

 

public class Singleton{ 
	private static Singleton instance=null; 
	private Singleton(){} 
	public static synchronized Singleton getInstance(){ 
		if(instance==null){ 
			instance=new Singleton(); 
		} 
		return instance; 
	} 
} 
 

 

但很多时候我们通常会认为锁定整个方法的是比较耗费资源的,代码中实际会产生多线程访问问题的只有 instance = new Singleton(); 这一句,

为了降低 synchronized 块性能方面的影响,只锁定instance = new Singleton(); 这一句,“weishuang”回帖中使用的就是这种方式:

 

 

public class Singleton{ 
	private static Singleton instance=null; 
	private Singleton(){} 
	public static Singleton getInstance(){ 
		if(instance==null){ 
			synchronized(Singleton.class){ 
				instance=new Singleton(); 
			} 
		} 
		return instance; 
	} 
} 
 

 

分析这种实现方式,两个线程可以并发地进入第一次判断instance是否为空的if 语句内部,第一个线程执行new操作,第二个线程阻断,当第一个线程执行完毕之后,第二个线程没有进行判断就直接进行new操作,所以这样做也并不是安全的。

 

为了避免第二次进入synchronized块没有进行非空判断的情况发生,添加第二次条件判断,就像“tomorrow009”在帖子中回复的示例一样

 

public static Singleton getInstance(){   
    if(instance == null){   
        synchronize{   
           if(instance == null){   
              instance =  new Singleton();    
           }   
        }   
    }   
    return instance;
}  

 

 

这样就产生了二次检查,但是二次检查自身会存在比较隐蔽的问题,查了Peter HaggarDeveloperWorks上的一篇文章,对二次检查的解释非常的详细:

“双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。”

 

其实找到这篇文章之后,我的问题基本上就已经可以解决了,但是看到回帖的同学们也有一些和我一样的问题,还想把这个问题继续梳理一遍。

 

使用二次检查的方法也不是完全安全的,原因是 java 平台内存模型中允许所谓的“无序写入”会导致二次检查失败,所以使用二次检查的想法也行不通了。

 

Peter Haggar在最后提出这样的观点:“无论以何种形式,都不应使用双重检查锁定,因为您不能保证它在任何 JVM 实现上都能顺利运行。”

 

"netrice"在回复中提到了使用“java5以后的volatile关键字”,用volatile关键字来声明变量,声明成 volatile 的变量被认为是顺序一致的,即,不是重新排序的。但是volatile关键字的特性并不适用于这篇帖子所讨论的问题关键。

 

通过上面的分析,可以看到使用懒汉式的lazy方式实现单例弯弯绕太多,在单线程编程的情况下懒汉式单例实现是没有任何问题的,如果在多线程的情况下,我们需要比较小心,对getInstances()方法加上synchronized关键字,这样虽然可能有一些性能上的牺牲,但是更加的安全。绕了这么大的一个弯,又回来了:

 

/* 安全的方式 1 */
public class Singleton{ 
	private static Singleton instance=null; 
	private Singleton(){} 
	public static synchronized Singleton getInstance(){ 
		if(instance==null){ 
			instance=new Singleton(); 
		} 
		return instance; 
	} 
} 
  

Peter Haggar提到的另外一种实现方式是这样的,放弃使用 synchronized 关键字,而使用 static 关键字:

 

/* 安全的方式 2 */
public class Singleton {

  private static Singleton instance = new Singleton();

  private Singleton() {}

  public static Singleton getInstance() {
    return instance;
  }

}

 

这种方式没有使用同步,并且确保了调用static getInstance()方法时才创建Singleton的引用(static 的成员变量在一个类中只有一份)。

 

还有“keshin”提到的方式则更加灵巧,没有使用同步但保证了只有一个实例,还同时具有了Lazy的特性(出自Lazy Loading Singletons

 

/* 安全的方式 3 */
public class ResourceFactory {   
    private static class ResourceHolder {   
        public static Resource resource = new Resource();   
    }   
  
    public static Resource getResource() {   
        return ResourceFactory.ResourceHolder.resource;   
    }   
  
    static class Resource {   
    }   
}  
  

上面的方式是值得借鉴的,在ResourceFactory中加入了一个私有静态内部类ResourceHolder ,对外提供的接口是 getResource()方法,也就是只有在ResourceFactory .getResource()的时候,Resource对象才会被创建,

 

这种写法的巧妙之处在于ResourceFactory 在使用的时候ResourceHolder 会被初始化,但是ResourceHolder 里面的resource并没有被创建,

 

这里隐含了一个是static关键字的用法,使用static关键字修饰的变量只有在第一次使用的时候才会被初始化,而且一个类里面static的成员变量只会有一份,这样就保证了无论多少个线程同时访问,所拿到的Resource对象都是同一个。


饿汉式的实现方式虽然貌似开销比较大,但是不会出现线程安全的问题,也是解决线程安全的单例实现的有效方式。

 

至于ThreadLocal,我认为还是应该由使用场景来决定。

 

在《Java与模式》中,作者提出:“饿汉式单例类可以在Java语言实现,但不易在C++内实现,因为静态初始化在C++里没有固定的顺序,因而静态的instance变量的初始化与类的加载顺序没有保证,可能会出问题。这就是为什么GoF在提出单例类的概念时,举的例子是懒汉式的。他们的书影响之大,以致Java语言中单例类的例子也大多是懒汉式的。实际上,本书认为饿汉式单例类更符合Java语言本身的特点。”

 

由此可见在应用设计模式的同时,分析具体的使用场景来选择合适的实现方式是非常必要的。

 

寻找问题解决过程中找的一些参考资料:

锁定老贴子 主题:【转】单例模式完全剖析

双重检查锁定及单例模式

Lazy Loading Singletons

 

因为在精华帖中没有找到很流畅解释这个问题的内容才发了这个帖子,还是很不幸的被评为了新手帖,但如果下次有面试官问有关线程安全的单例模式问题,我想我知道该怎么回答了。

 

 

 

 

 

 

 

分享到:
评论
45 楼 panshunchang 2010-05-27  
liuzhiqiangruc 写道
viei 写道
我一般这样写

public class Singleton{
static class SingletonHolder{
  static Singleton instance=new Singleton();
}

public static Singleton getInstance(){
  return Singleton.instance();
}
}

最早从google的一个叫lee的人那里学来的,现在基本都这样写


恩,这样写确实精妙,避免了对静态数据域直接赋值所带来的浪费。不用在不用的时候创建对象。
呵呵,我自己说的拗口了。



Singleton.instance();
的instance()方法哪里定义的?》》》》》》》》》》》》》》》
44 楼 liuzhiqiangruc 2010-05-27  
viei 写道
我一般这样写

public class Singleton{
static class SingletonHolder{
  static Singleton instance=new Singleton();
}

public static Singleton getInstance(){
  return Singleton.instance();
}
}

最早从google的一个叫lee的人那里学来的,现在基本都这样写


恩,这样写确实精妙,避免了对静态数据域直接赋值所带来的浪费。不用在不用的时候创建对象。
呵呵,我自己说的拗口了。
43 楼 panshunchang 2010-05-27  
shenjianwangyi 写道
xl10230 写道
tomorrow009 写道
Singleton模式分两种,“懒汉”和“恶汉” 恶汉模式也就是前面很多人提到的

public class Singleton{
   private static Singleton instance = new Singleton();
   private Singleton(){
   //私有化构造函数.
   };
   public static Singleton getInstance(){
       return instance;
   }

}

由于实例在类加载时就已经创建,所以不存在线程同步问题,如果该Singleton初始化时不需要很大的开销(比如io操作/数据库连接)之类的,通常用这种办法就可以了.

某些情况下我们希望实例只有被第一次用到的时候才创建,那么这时候就使用“懒汉”模式,初学者通常会采用LZ的写法,正如面试官所说,这样会有线程同步问题,而导致多个实例被创建。如果在 getInstance()方法前面加上synchronize,又会大大降低系统性能。其实我们需要考虑的是,究竟要同步哪里? 我们只需要同步new Singleton()这个部分,保证只有一个实例被创建出来即可,而无须同步整个getInstance()方法,那么就可以考虑这样做
    public static Singleton getInstance(){
        if(instance == null){
            synchronize{
               if(instance == null){
                  instance =  new Singleton(); 
               }
              
            }
        }
    }





  应该就是这样了。

顶一个double checked模式



真搞不懂,这样跟

    public static Singleton getInstance(){
            synchronize{
               if(instance == null){
                  instance =  new Singleton();
               }
             
            }
    }

有什么区别,多此一举吗?
42 楼 lixia0417 2010-04-20  
xprayc 写道
通常有两种常见的策略实现单例,一如lz所言,即所谓lazy形式的。如果害怕线程安全问题,而又不想用synchronized影响性能的话,不如用另一种:

public class Singleton { 
     
    private Singleton() {} 
    // 载入class时立即初始化
    private static Singleton instance = new Singleton(); 
 
    public static Singleton getInstance() { 
       
        return instance; 
    } 


当然这种也有缺点,instance会立即初始化,而不管是否实际用到。:)



多谢,但是这样的话,貌似也不能算作是“安全”的单例实现吧...
LZ,这句话什么意思,是说因为不管用不用都得实例化耗费资源,这样的实现方式不太好?
41 楼 Solstice 2009-12-23  
tomorrow009:

Your double checked locking is broken.

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
40 楼 凤舞凰扬 2009-12-06  
      本来不太想为这样一个话题继续太多口水的,但是看到很多人还是很积极地响应,也看到很多人总是有各种各样的误区。想想,还是稍微说点也好。
      单例,简单讲也就是一个实例,单例模式,简单讲就是控制对象只有一个。好,也让大家理解以下几个问题:
1. 单例模式中的单例是全局的还是局部的?(没有人明确过这个问题,也因为这个问题产生了许多模式与反模式的概念)这里的全局和局部究竟是怎么样的概念,全局究竟是指一个JVM还是指一个系统(也许会多个JVM甚至分布式存在),这里的局部又是指一个线程调用的堆栈,还是一个模块或者说一个系统中的JVM? 不同的理解,不同的应用,对于单例模式有着完全不同的设计实现了。(用ThreadLocal的朋友又是否清楚它所应用的全局和局部了么?)
2. 一个单例模式的应用,究竟是希望对于创建者来说,是多次创建都只是返回同一个实例,还是对于使用者来说,我们使用的是同一个实例呢?或者说又是两者皆可?如果只是使用的是同一个实例,那么单例模式又有许多变形的方式,比如spring中的container管理bean实例一样。
3. 单例模式中实例的创建代销又是怎么样(不考虑分布式的情况),是非常大还是非常小呢?如果非常小,采用所谓的懒汉做法,又为何不可?如果是非常大?那是不是需要考虑延迟装载呢?如果延迟装载又是否会对第一次的应用有比较大的影响呢?这些都决定了单例如何的实现。
4. 如果单例模式使用的访问远可能多于并发创建的访问,过多的线程安全同步控制又是否值得呢?这个时候所谓的double check代码从某种程度上来讲又增加了什么样的代销?
      其实任何一个模式都有自己的特点,都有自己的应用场景,而一种模式的实际实现方案也是一样。在闫宏的《java与模式》中更多地是讨论了不同方案的特点,从来不会有一种方案适用全部的地方。现在就是有太多的朋友只会copy,paste,只会抄袭,多了,自然也就成反模式,成方面教材了。而那些鼓吹反模式的朋友又是否真正了解一个模式是如何成为反模式的,真正了解模式的应用场景么?
     想告诉楼上各位、楼主的是,不要简单评价一种实现是否正确,而是要看它是否用在正确的场景中。
39 楼 21xz 2009-12-05  
没想到单例模式如此复杂,上次考试时幸好没有在这上面刁难 哈哈
38 楼 keshin 2009-12-02  
还有一种:
 
public class Something {
	private Something() {
	}

	private static class LazyHolder {
		private static final Something something = new Something();
	}

	public static Something getInstance() {
		return LazyHolder.something;
	}
}

原理参见
http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
37 楼 wzw00001 2009-12-01  
keshin 写道
public class ResourceFactory {
    private static class ResourceHolder {
        public static Resource resource = new Resource();
    }

    public static Resource getResource() {
        return ResourceFactory.ResourceHolder.resource;
    }

    static class Resource {
    }
}

java concurrency in practice中建议的方式



又学习了单例模式一种新的写法
36 楼 flashing 2009-12-01  
xprayc 写道
通常有两种常见的策略实现单例,一如lz所言,即所谓lazy形式的。如果害怕线程安全问题,而又不想用synchronized影响性能的话,不如用另一种:

public class Singleton { 
     
    private Singleton() {} 
    // 载入class时立即初始化
    private static Singleton instance = new Singleton(); 
 
    public static Singleton getInstance() { 
       
        return instance; 
    } 


当然这种也有缺点,instance会立即初始化,而不管是否实际用到。:)


这个缺点根本就不是缺点。你用不到这个类为什么访问它呢,访问它获得实例必须初始化。说白了这个所谓缺点仔细想明白,你会发现这是最佳实现方式。
35 楼 sumaolin 2009-12-01  
不太懂啊!
34 楼 pipilu 2009-12-01  
香克斯 写道
bencode 写道
keshin 写道
public class ResourceFactory {
    private static class ResourceHolder {
        public static Resource resource = new Resource();
    }

    public static Resource getResource() {
        return ResourceFactory.ResourceHolder.resource;
    }

    static class Resource {
    }
}

java concurrency in practice中建议的方式



这个好, 延迟初始化,线程安全,效率高(没有使用同步锁,而由类加载器保证) 简洁



凤舞凰杨都跟你们说了多看看书,还是有人搞出什么double check啊之类的来.
上面这个是目前最简单有效的单例方式.
就是一堆人视而不见


我也看过developerworks上讨论的double-check的问题。但据说那个问题在jdk1.5已经解决了。http://zhangle.iteye.com/blog/259991
应该可以像http://www.ibm.com/developerworks/cn/java/j-dcl.html中所说的那样分析出来的,但我电脑上目前没安装Visual Studio,先留言在这,回去试出来了再说。

……楼上已经说了。
33 楼 pattern 2009-12-01  
香克斯 写道
bencode 写道
keshin 写道
public class ResourceFactory {
    private static class ResourceHolder {
        public static Resource resource = new Resource();
    }

    public static Resource getResource() {
        return ResourceFactory.ResourceHolder.resource;
    }

    static class Resource {
    }
}

java concurrency in practice中建议的方式



这个好, 延迟初始化,线程安全,效率高(没有使用同步锁,而由类加载器保证) 简洁



凤舞凰杨都跟你们说了多看看书,还是有人搞出什么double check啊之类的来.
上面这个是目前最简单有效的单例方式.
就是一堆人视而不见


是的上面是最简单有效的 Lazy Loading Singletons实现方法,关于几种Singleton实现方法,Google工程师Bob Lee有个很好的帖子 http://crazybob.org/2007/01/lazy-loading-singletons.html。

总结成以下三点:

1. 使用Synchronized同步getInstance方法, 简单有效适合所有的JVM版本,但Lock contention带来性能开销
2. 使用Double-checked Locking 和只同步create instance的部分,同时必须声明单列变量为volatile,否则同样不是完全线程安全的。同样由于Java Memory Model的对volatile的模糊定义,这个模式无法使用在5之前的JVM。新的JMM对volatile定义更明确,compound operation (比如++, get-set)也是原子性的,所以DCL可以放心使用在Java 5中。使用在5以后版本,可以提升10%性能(bob lee测试)
3. 最快的方法还是Lazy Loading Singletongs, 它从Initialization on Demand Holder (IODH) 模式演化而来, 针对这个模式Effective Java 第48条也有很详细的描述。

最后还是要看情况来合理使用各种技巧, 很多时候其实最老土的发法一还是很好很管用的




32 楼 thihy 2009-12-01  
fangin 写道
tomorrow009 写道
Singleton模式分两种,“懒汉”和“恶汉” 恶汉模式也就是前面很多人提到的

public class Singleton{
   private static Singleton instance = new Singleton();
   private Singleton(){
   //私有化构造函数.
   };
   public static Singleton getInstance(){
       return instance;
   }

}

由于实例在类加载时就已经创建,所以不存在线程同步问题,如果该Singleton初始化时不需要很大的开销(比如io操作/数据库连接)之类的,通常用这种办法就可以了.

某些情况下我们希望实例只有被第一次用到的时候才创建,那么这时候就使用“懒汉”模式



第一种方式(加载时创建实例)有什么问题?类的加载机制是第一次调用static方法时类才加载,也就是在调用getInstance()方法时Singleton才被加载,这样跟第二种的加载时间有什么不同?不都是第一次使用时才加载吗?
以上是我的困惑,希望楼下有人给我解惑

同问。
只在调用静态方法getInstance时,instance 才会初始化。至少在JDK1.6是如此的。又何必去再里面定义一个内部类,加一个静态变量,在getInstance方法里面调用此变量呢。很疑惑。
PS 越看越觉得书读的少啊。。。
31 楼 wy19280469 2009-12-01  
aniu2008 写道
Hibernate的文档时看到了关于使ThreadLocal管理多线程访问的部分。具体代码如下

1.  public static final ThreadLocal session = new ThreadLocal();
2.  public static Session currentSession() {
3.      Session s = (Session)session.get();
4.      //open a new session,if this session has none
5.   if(s == null){
6.      s = sessionFactory.openSession();
7.      session.set(s);
8.   }
      return s;
9. }

我们逐行分析
1。 初始化一个ThreadLocal对象,ThreadLocal有三个成员方法 get()、set()、initialvalue()。
    如果不初始化initialvalue,则initialvalue返回null。
3。session的get根据当前线程返回其对应的线程内部变量,也就是我们需要的net.sf.hibernate.Session(相当于对应每个数据库连接).多线程情况下共享数据库链接是不安全的。ThreadLocal保证了每个线程都有自己的s(数据库连接)。
5。如果是该线程初次访问,自然,s(数据库连接)会是null,接着创建一个Session,具体就是行6。
6。创建一个数据库连接实例 s
7。保存该数据库连接s到ThreadLocal中。
8。如果当前线程已经访问过数据库了,则从session中get()就可以获取该线程上次获取过的连接实例。


LZ这个也没谈到Hibernate 你们干嘛要说Hibernate中的ThreadLocal啊 - - 崩溃啊啊!!!!!

就是一个管理Sessin的类
30 楼 wy19280469 2009-12-01  
不知道我们这个类是不是你面试者问的线程单利类

我一个类实现Runalbe接口,
有一个BlockingQueue queue = new LinkedListBlockingQueue();(大吞吐量)
然后有一个缓存池线程池 Executer exec = Executors.newFixedThreadPool(3);

然后这个类写成单例的,private 构造器

在run方法里实现另一个县城
用exec.execute实现

        /**
	 * 任务队列
	 */
	private static final BlockingQueue<Map> queue = new LinkedBlockingQueue<Map>(30);

	/**
	 * 线程池
	 */
	private static final ExecutorService exec = Executors.newFixedThreadPool(3);

        /**
	 * 任务队列
	 */
	private static final BlockingQueue<Map> queue = new LinkedBlockingQueue<Map>(30);

	/**
	 * 线程池
	 */
	private static final ExecutorService exec = Executors.newFixedThreadPool(3);
     
       public static synchronized DataSendMgr getInstance(){
		if( instance == null ){
			if( Constants.getDbAgentIsWorking() ){
				instance = new DataSendMgr();
				new Thread(instance).start();
				 
			} 
		return instance;
	}

      public void run() {
		Map execMap = null;
		while(runFlag){
		    try {
		       try {
			 execMap = queue.take();
			    if( STOP_FLAG_OBJECT.equals(execMap) ){
			  	break;
			}
				exec.execute( new SendData( service.getDatagramSession(), execMap) );
				} catch (SocketException e) {
					service.quit();
					logger.error("SenderService Error::" + MethodUtil.printExceptionErr(e));
				}
			} catch (InterruptedException e) {
				logger.error("DataSendMgr Thread take Object from queue Error::" + e.getMessage());
			}
			execMap = null;
		}
		if( logger.isInfoEnabled() ){
			logger.info( "DataSendMgr Thread stop running..." );
		}
	}



一部分代码! 总之这个线程是单例的,然后由线程池来开启另一个子线程
29 楼 香克斯 2009-12-01  
bencode 写道
keshin 写道
public class ResourceFactory {
    private static class ResourceHolder {
        public static Resource resource = new Resource();
    }

    public static Resource getResource() {
        return ResourceFactory.ResourceHolder.resource;
    }

    static class Resource {
    }
}

java concurrency in practice中建议的方式



这个好, 延迟初始化,线程安全,效率高(没有使用同步锁,而由类加载器保证) 简洁



凤舞凰杨都跟你们说了多看看书,还是有人搞出什么double check啊之类的来.
上面这个是目前最简单有效的单例方式.
就是一堆人视而不见
28 楼 i2534 2009-12-01  
其实,我想问下大牛们,为什么不用lock来代替synchronize呢?try {lock}finally {unlock}?
27 楼 chunquedong 2009-12-01  
《effective java》这本书中也总结了好多种单例的实现方法,大家不妨看看。
26 楼 shenjianwangyi 2009-12-01  
xl10230 写道
tomorrow009 写道
Singleton模式分两种,“懒汉”和“恶汉” 恶汉模式也就是前面很多人提到的

public class Singleton{
   private static Singleton instance = new Singleton();
   private Singleton(){
   //私有化构造函数.
   };
   public static Singleton getInstance(){
       return instance;
   }

}

由于实例在类加载时就已经创建,所以不存在线程同步问题,如果该Singleton初始化时不需要很大的开销(比如io操作/数据库连接)之类的,通常用这种办法就可以了.

某些情况下我们希望实例只有被第一次用到的时候才创建,那么这时候就使用“懒汉”模式,初学者通常会采用LZ的写法,正如面试官所说,这样会有线程同步问题,而导致多个实例被创建。如果在 getInstance()方法前面加上synchronize,又会大大降低系统性能。其实我们需要考虑的是,究竟要同步哪里? 我们只需要同步new Singleton()这个部分,保证只有一个实例被创建出来即可,而无须同步整个getInstance()方法,那么就可以考虑这样做
    public static Singleton getInstance(){
        if(instance == null){
            synchronize{
               if(instance == null){
                  instance =  new Singleton(); 
               }
              
            }
        }
    }





  应该就是这样了。

顶一个double checked模式

相关推荐

    Java初级开发面试题

    Java面试题包括但不限于: Java基础知识:语法、面向对象编程、...Java设计模式:单例模式、工厂模式、代理模式等。 网络编程:TCP/IP、HTTP、Web Services等。 数据库相关:SQL语句、数据库连接池、事务管理等。

    2023Java高频面试题

    Java面试题主要涉及Java语言本身、常用的Java框架和技术、面向对象编程、多线程编程、算法和数据结构等方面。通常包括以下主要内容: Java基础知识:Java的基本数据类型、变量、运算符、控制语句等基础概念。 面向...

    NET面试题-多线程编程与线程同步1

    2. 为什么GUI不支持跨线程访问控件 3. 简述后台线程和前台线程的区别 4. 说说常用的锁,lock是一种什么样的锁 5. lock为什么要锁定一个参数,可

    Java基础语法面试题.docx

    Java基础语法面试题资源通常是指帮助准备...设计模式:介绍常见的设计模式,如单例模式、工厂模式、观察者模式等。 常见算法和数据结构:可能包含一些常见的算法问题,如查找、排序、递归等,以及与之相关的数据结构。

    Java 基础面试题

    该文档主要整理了常见的Java基础面试题,包含以下内容: 1. 抽象类和接口的区别 2. 什么时候使用抽象类,什么时候使用接口 3. 八大基本数据类型,所占字节数 4. List、Set、Map的区别 5. 什么情况下使用List、...

    北京百度java面试题大全

    Java面试题是针对Java编程语言的技术和知识的一系列问题,用于考察面试者在Java开发方面的能力和...设计模式:涉及常见的设计模式,如单例模式、工厂模式、观察者模式等。 Java框架和技术:包括Spring、Hibernate、My

    mysql面试题-mysql经典面试题目-数据库的基本概念-SQL语法-事务处理-索引优化-性能调优-mysql-面试题目

    如何实现线程安全的单例模式? 什么是Java中的生命周期回调方法?列举一些常见的生命周期回调方法。 什么是Java中的注解处理器?如何自定义和使用注解处理器? 什么是Java中的并发编程?列举一些常见的并发类和...

    Java实例高难度面试题及解析 - 展现你的编程实力!

    您将了解如何正确创建对象实例、访问实例的成员变量和方法、实现对象的拷贝(包括浅拷贝和深拷贝)、判断对象相等性、管理对象的生命周期、实现线程安全的单例模式等。此外,我们还探讨了对象的哈希码、重写equals()...

    java面试题.pdf

    10道Java面试题及详细解答 1.Java中多态的实现方式是什么? 2. Java中如何避免空指针异常? 3. Java中垃圾回收的机制是什么? 4. Java中什么是反射? 5. Java中什么是线程安全? 6. Java中抽象类和接口的区别是什么...

    美团Java 岗 154 道面试题.zip

    请用 Java 写出线程安全的单例模式 100.在 Java 中,什么叫观察者设计模式(observer design pattern)? 101.使用工厂模式最主要的好处是什么?在哪里使用? 102.举一个用 Java 实现的装饰模式(decorator design ...

    2024年Java高工面试题 2024年Java高工面试题 2024年Java高工面试题

    2024年Java高工面试题 JVM虚拟机:堆、方法区(元空间)、栈(线程)、本地方法栈、程序计数器 栈帧:局部变理表、操作数栈、动态链接、方法出口 对象组成:对象头(Mark Word、KlassPointer类型指针、数组长度)、...

    JAVA工程师面试题和一些经典题

    JAVA工程师面试题和一些经典题

    JAVA-SSH面试题

    struts1.2 Action是单例模式的并且必须是线程安全的,因为仅有一个Action的实例来处理所有的请求。 单例策略限制了Struts1.2 Action能做的事情,并且开发时特别小心。Action资源必须是线程安全的或同步的。 struts...

    java面试题库2021.pdf

    目录 一、 JavaSE 部分 1、 Java 基础 ①Java 基础部分(基本语法, Java 特性等) ②关键字 ③面向对象 ...①单例模式 3、 行为型模式 ①策略模式 ②观察者模式 4、 所有模式汇总 十、 场景题 十一、 UML

    java社招二面面试题有哪些

    什么是单例模式 @RequestMapping有什么参数 ConcurrentHashMap怎么实现的,1.7和1.8的区别 执着,怎么解决一个问题 线程的五种状态 sleep和wait的区别 collection和map的区别 集合哪些是排序的 List的Conllections....

    Offers:java学习及找工作记录。包括java基础,并发,数据库,算法,网络,设计模式,spring等参考书籍,jdk1.8源码,demo,笔面试题记录及阿里巴巴java开发手册等

    优惠记录申请Java开发工程师的学习资料演示死锁螺纹池不安全集合类volatile特性线程安全单例模式CAS应用ABA问题信号倒数计时循环屏障阿里巴巴java开发手册阿里官方发布1000道互联网大厂Java工程师面试题源码学院发布...

    Python 全面的面试题

    * [16 单例模式](#16-单例模式) * [1 使⽤__new__⽅法](#1-使⽤__new__⽅法) * [2 共享属性](#2-共享属性) * [3 装饰器版本](#3-装饰器版本) * [4 import⽅法](#4-import⽅法) * [17 Python中的作⽤域](#17-...

    java面试题

    如何控制两种框架中的单例模式? 74 73. Spring 75 73.1. Spring 简介 75 73.2. 为什么要用Spring? 76 73.3. spring工作机制或工作原理 76 73.4. Spring是什么?根据你的理解详细谈谈你的见解。 76 73.5. 项目中如何...

    2024最新的面试题来了

    模块化编程与热插拔、Java单例防止反射漏洞攻击、JVM常用配置参数、线程调度器和时间分片是计算机编程中一些重要的概念和技术。 模块化编程是一种将复杂的程序分解为独立的、可重用的模块的编程方法。它提供了更好...

Global site tag (gtag.js) - Google Analytics