JAVA的单例模式,顺便谈下类的同步方法和对象的同步方法

2012/1/12 追加

新看到三种单例模式,备忘 - 倚楼无语F5 - 博客园 - Nightly

  • 单线程下的单例
  • 多线程下的单例
  • 类的同步方法和对象的同步方法。

 

单线程单例

单例(Singleton)的定义如下, 场景多是全局访问。

Ensure a class only has one instance, and provide a global point of access to it 。 

 

写一个单例类往简单说,只要记住三点即可。

1、一个私有的构造器。
2、含有一个自身的实例。
3、提供一个静态方法访问实例

public class Singleton {
    // 2
    
private static Singleton content;
    
private int cnt = 0;
    // 1
    
private Singleton(){
        
    cnt = new Integer(100);
   
}
    // 3
    
public static Singleton getInstance(){
       
if(content == null){
            content 
= new Singleton();
        }
        
return content;
    }
    
    
public synchronized void increase(){
        System.out.println(
++cnt);
    }

}


多线程下的单例
如果在存在多线程的话,必须要静态的访问方法加上同步标记synchronized。否则可能会被多次实例化

package oodesign;

public class Singleton {

    
private static Singleton content;
    
private int cnt = 0;
    
    
private Singleton(){
        
try {
            System.out.println(
"初始化实例...");
            Thread.sleep(
3000);
            cnt 
= new Integer(100);
        } 
catch (InterruptedException e) {}
    }
    
    
public static synchronized Singleton getInstance(){
        System.out.println(
"获取单例...");
        
if(content == null){
            content 
= new Singleton();
        }
        
return content;
    }
    
    
public synchronized void increase(){
        System.out.println(
++cnt);
    }
    
    
public static synchronized void blocking(){
        System.out.println(
"阻塞一会3秒....");
        
try {
            Thread.sleep(
3000);
        } 
catch (InterruptedException e) {}
        System.out.println(
"阻塞结束....");
        
    }
}

 

类的同步方法和对象的同步方法

因为谈到同步方法,正好再复习下锁。

对象有锁、一个对象的同步方法被访问。这个对象就上锁了,其他线程再访问这个方法或者这个对象的其他同步方法都是不行的。

类也有锁。但类的锁不会和这类实例的锁冲突。他们之间是独立的。下面给出一段代码进行验证。

package oodesign;

public class Test {
    
public static void main(String[] args) throws InterruptedException {
        
// 通过给getInstance方法加上synchronized以避免多次实例化
        new TestSingleton().start();
        
new TestSingleton().start();
        
        
// 测试类的同步锁和对象的同步锁
        
// 准备对象
        Singleton singleton = Singleton.getInstance();
        
        
// 给类加上锁 ,阻塞三秒
        new BlockingSingleton().start();
        
// 停一瞬间确保顺序
        Thread.sleep(10);
        
// 使用对象的同步方法
        new TestSingleton2(singleton).start();
        
// 使用类的同步方法  然后 使用对象的同步方法
        new TestSingleton().start();
        
    }
}

class TestSingleton extends Thread {
    
public void run() {
        Singleton.getInstance().increase();
    }
}
class BlockingSingleton extends Thread {
    
public void run() {
        Singleton.blocking();
    }
}
class TestSingleton2 extends Thread {
    Singleton singleton;
    
public TestSingleton2(Singleton singleton) {
        
this.singleton = singleton;
    }
    
public void run() {
        singleton.increase();
    }
}

 

 结果:

说明1、多次访问、只实例化了一次。

说明2、阻塞了类的同步方法,但并不妨碍对类实例对象的同步方法的访问

说明3、阻塞类的同步方法,对该类其他的同步方法有影响

获取单例...
初始化实例...  // 说明1
获取单例...
101
获取单例...
102
阻塞一会3秒.... // 说明2
103           // 说明2
阻塞结束....
获取单例...    // 说明3
104
posted @ 2011-08-09 23:05  倚楼无语F5  阅读(571)  评论(0编辑  收藏  举报