单例模式应用场景之一: 确保共享的数据,共享的操作,在多线程下,线程安全。其实现方式是:控制资源的使用,通过线程同步来控制资源的并发访问;
疑问:一直都不理解为什么可以做到,不使用单例,为什么又做不到?
1、单例测试场景
单例类:
public class ShareResourceSingleton {
private static ShareResourceSingleton instance = new ShareResourceSingleton();
private ShareResourceSingleton() {
}
public static ShareResourceSingleton getInstance() {
return instance;
}
public synchronized void testShareResourcePrototype() {
System.out.println("testShareResourcePrototype" + Thread.currentThread().getName());
try {
Thread.currentThread().sleep(5500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("testShareResourcePrototype" + Thread.currentThread().getName() + "sleep over");
}
}
测式主类
public class TestThread {
public static void main(String[] args) {
Thread t1 = new Thread1();
Thread t2 = new Thread1();
t1.start();
t2.start();
}
}
线程1
public class Thread1 extends Thread{
public void run(){
/*ShareResourcePrototype shareResourcePrototype = new ShareResourcePrototype();
shareResourcePrototype.testShareResourcePrototype();*/
ShareResourceSingleton shareResourceSingleton = ShareResourceSingleton.getInstance();
shareResourceSingleton.testShareResourcePrototype();
}
}
输出:
testShareResourcePrototypeThread-0
testShareResourcePrototypeThread-0sleep over
testShareResourcePrototypeThread-1
testShareResourcePrototypeThread-1sleep over
2、多例测试场景
多例类:
public class ShareResourcePrototype {
private int i = 0;
public synchronized void testShareResourcePrototype() {
System.out.println("testShareResourcePrototype" + Thread.currentThread().getName());
try {
Thread.currentThread().sleep(5500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("testShareResourcePrototype" + Thread.currentThread().getName() + "sleep over");
}
}
线程1
public class Thread1 extends Thread{
public void run(){
ShareResourcePrototype shareResourcePrototype = new ShareResourcePrototype();
shareResourcePrototype.testShareResourcePrototype();
/* ShareResourceSingleton shareResourceSingleton = ShareResourceSingleton.getInstance();
shareResourceSingleton.testShareResourcePrototype();*/
}
}
输出:
testShareResourcePrototypeThread-0
testShareResourcePrototypeThread-1
testShareResourcePrototypeThread-0sleep over
testShareResourcePrototypeThread-1sleep over
1、以上输出说明,在使用单例时,同步代码块仅能被一个线程访问,直到线程执行完同步代码块,释放锁。其它线程才能进入此代码块。这样就达到了控制并发访问的目的,实现了线程安全
所以使用单例+线程同步 ,可以满足一些特定的场景,比如:打印,文件访问等需要全局控制并发访问需求
2、使用多例时,同步代码块没有起到互斥的作用,可以被多线程同时访问
回答之前的疑问:
不理解,并不是不理解单例模式,而是不理解synchronized 这个的作用。
synchronized 只会锁定调用其同步方法的那个对象,意思是,多线程只有使用同一个对象(实例)时,才可以达到同步方法互斥访问的效果