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);
}
}
// 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("阻塞结束....");
}
}
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();
}
}
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
初始化实例... // 说明1
获取单例...
101
获取单例...
102
阻塞一会3秒.... // 说明2
103 // 说明2
阻塞结束....
获取单例... // 说明3
104