架构师之路第四天

单例和多线程

ThreadLocal概念:线程局部变量,是一个多线程间并发访问变量的解决方案。与其synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用空间换时间的手段,为每个线程提供变量的独立副本,以保障线程的安全。

从性能上说,ThreadLocal不具备绝对的优势,在并发不是很高的时候,加锁的性能会更好,但作为一套与锁完全无关的线程安全解决方案,在高并发或者竞争激烈的场景,使用ThreadLocal可以在一定的程度上减少锁竞争。

ThreadLocl的代码案例如下:

public class Test4 {
	private ThreadLocal<String> list = new ThreadLocal<String>();
	public void setVlaue(String value)
	{
		list.set(value);
	}	
	public void getValue()
	{
		System.out.println("当前的线程:"+Thread.currentThread().getName()+";值为:"+list.get());
	}
	public static void main(String[] args) throws Exception { 
		Test4 test1 = new Test4();
		Thread t1 = new Thread(new Runnable() {		
			@Override
			public void run() {
					try {
						test1.setVlaue("a");
						test1.getValue();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
		},"t1");	
       Thread t2 = new Thread(new Runnable() {		
			@Override
			public void run() {
					try {
						Thread.sleep(1000);
						test1.getValue();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
		},"t2");     
       t1.start();
       t2.start();
	}
}

运行的结果是:

当前的线程:t1;值为:a
当前的线程:t2;值为:null

解释:ThreadLocal完全不提供锁,而使用空间换时间的手段,为每个线程提供变量的独立副本。也就是线程间的ThreadLocal是不可见的,互相不影响的。

单例与多线程

单例模式最常见的就是懒汉式和饿汉式,名字的命名就是依据与创建对象的先后顺序。其中在实际的开发中使用的单例模式有两种:一是静态内部类,二是懒汉式的双重判断。

静态内部类:

public class Test5 {
	// 静态内部类
	private static class Singletion{
		private static Singletion singletion = new Singletion();
	}
	// 获取实例
	public static Singletion getInstance()
	{
		return Singletion.singletion;
	}
}

懒汉式的双重判断(只有一重判断的案例):

public class Test6 {

	// 静态内部类
	private static Test6 test = null;

	public static Test6 getInstance() {
		if (test == null) {
			try {
				// 模拟业务场景
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			synchronized (Test6.class) {
				//if (test == null) {
					test = new Test6();
				//}
			}
		}
		return test;
	}

	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					System.out.println(Test6.getInstance().hashCode());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t1");

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					System.out.println(Test6.getInstance().hashCode());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t2");
		
		Thread t3 = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					System.out.println(Test6.getInstance().hashCode());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t3");	
		t1.start();
		t2.start();
		t3.start();
	}
}

输出的结果:

1384277657
1804397488
619028145

懒汉式的双重判断(双重判断的案例):

public class Test6 {

	// 静态内部类
	private static Test6 test = null;

	public static Test6 getInstance() {
		if (test == null) {
			try {
				// 模拟业务场景
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			synchronized (Test6.class) {
				// 这里需要判断非空
				if (test == null) {
					test = new Test6();
				}
			}
		}
		return test;
	}
	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {				System.out.println(Test6.getInstance().hashCode());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {			System.out.println(Test6.getInstance().hashCode());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t2");	
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {				System.out.println(Test6.getInstance().hashCode());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t3");	
		t1.start();
		t2.start();
		t3.start();
	}
}

输出的结果是:

1384277657
1384277657
1384277657

 

 

猜你喜欢

转载自blog.csdn.net/javashareauthor/article/details/83343270
今日推荐