您的位置:首页 > 编程语言 > Java开发

Java多线程学习(四)

2016-03-06 19:36 405 查看
单例模式
1.1立即加载/饿汉模式
立即加载既为使用类的方法的时候已经将对象创建完毕。常见的实现方法就是直接new实例化。
public class MyObject {
private static MyObject myObject = new MyObject();
private MyObject(){}
public static MyObject getInstance(){
return myObject;
}
}
public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}

public static void main(String [] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

t1.start();
t2.start();
t3.start();
}
}
运行结果为三个线程输出的值相同。
1.2延迟加载/懒汉模式
延迟加载既为调用类的方法时,对象实例才被创建。常见实现方法为在get方法中进行new实例化。
public class MyObject {
private static MyObject myObject;
private MyObject(){}
public static MyObject getInstance(){
if(myObject == null){ myObject = new MyObject();}
return myObject;
}
}
public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}

public static void main(String [] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

t1.start();
t2.start();
t3.start();
}
}
运行结果为三个线程输出的值不同,取出了多个线程实例,与单例模式相违背。


延迟加载的解决方案
如上例所示的延迟加载方法,在多线程模式下是线程不安全的,那么就是以下几种解决方案吧!
①声明synchronized关键字
既然出现线程不安全问题是因为多个线程同时进入getInstance方法导致的,那么就给这个方法上锁,同一时间内只有一个线程能够访问。
public class MyObject {
private static MyObject myObject;
private MyObject(){}
synchronized public static MyObject getInstance(){
if(myObject == null){
myObject = new MyObject();
}
return myObject;
}
}
public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}

public static void main(String [] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

t1.start();
t2.start();
t3.start();
}
}
运行结果为三个线程输出的值相同。
但是这种方法的运行效率非常低下。
②尝试同步代码块
public class MyObject {
private static MyObject myObject;
private MyObject(){}
public static MyObject getInstance(){
synchronized (MyObject.class){
if(myObject == null){ myObject = new MyObject();}
}
return myObject;
}
}
public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}

public static void main(String [] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

t1.start();
t2.start();
t3.start();
}
}
运行结果为三个线程输出的值相同。
但是这相当于第一种给方法上锁的方式,效率同样低下。
③尝试给重要代码上锁
public class MyObject {
private static MyObject myObject;
private MyObject(){}
public static MyObject getInstance(){
if(myObject == null){
synchronized (MyObject.class){
myObject = new MyObject();
}
}
return myObject;
}
}
public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}

public static void main(String [] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

t1.start();
t2.start();
t3.start();
}
}
运行结果为三个线程输出的值不相同,并不是单例的。
这样的上锁方式虽然虽然提高了效率,但是仍有可能同时有多个线程进入if方法内部,等待执行同步代码块,因此获取了多个对象。
④使用DCL双检查锁机制
public class MyObject {
private static MyObject myObject;
private MyObject(){}
public static MyObject getInstance(){
if(myObject == null){
synchronized (MyObject.class){
if(myObject == null){
myObject = new MyObject();
}
}
}
return myObject;
}
}
public class MyThread extends Thread {
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}

public static void main(String [] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

t1.start();
t2.start();
t3.start();
}
}
运行结果为三个线程输出的值相同。
使用双重检查锁机制,成功的解决了懒汉模式遇到多线程的问题。DCL也是大多数多线程结合单例模式使用的解决方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: