线程同步与锁定_synchronized_单例模式_doubleCheckingJAVA178-179
2016-01-24 16:13
357 查看
来源:http://www.bjsxt.com/
一、S02E178_01线程同步与锁定1_synchronized
——由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
——由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块
——同步:并发,多个线程访问同一份资源(确保资源安全–>>线程安全)
1、同步块
——synchronized(引用类型或者this或者类.class){
}
2、同步方法
——synchronized
二、S02E179_01线程同步与锁定2_synchronized_单例模式_doubleChecking
一、S02E178_01线程同步与锁定1_synchronized
——由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
——由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块
——同步:并发,多个线程访问同一份资源(确保资源安全–>>线程安全)
1、同步块
——synchronized(引用类型或者this或者类.class){
}
2、同步方法
——synchronized
package com.test.thread.syn; public class SynDemo { public static void main(String[] args) { //真实角色 Web12306 web = new Web12306(); //代理 Thread t1 = new Thread(web, "路人甲"); Thread t2 = new Thread(web, "黄牛乙"); Thread t3 = new Thread(web, "攻城狮"); t1.start(); t2.start(); t3.start(); } } class Web12306 implements Runnable { private int num = 10;//1到10号 private boolean flag = true; @Override public void run(){ while(flag) { //test1(); //test2(); //test3(); //test4(); //test5(); test6(); } } //线程不安全 public void test1(){ if(num <= 0){ flag = false;//跳出循环 return; } try { Thread.sleep(500);//模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } //同步方法,线程安全,锁定正确 public synchronized void test2(){ if(num <= 0){ flag = false;//跳出循环 return; } try { Thread.sleep(500);//模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } //同步块,线程安全,锁定正确 public void test3(){ synchronized(this){ if(num <= 0){ flag = false;//跳出循环 return; } try { Thread.sleep(500);//模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } } //锁定范围不正确 public void test4(){ synchronized(this){ if(num <= 0){ flag = false;//跳出循环 return; } } try { Thread.sleep(500);//模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } //线程不安全,锁定资源不正确 public void test5(){ synchronized((Integer)num){ if(num <= 0){ flag = false;//跳出循环 return; } try { Thread.sleep(500);//模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } } //锁定范围不正确 public void test6(){ if(num <= 0){ flag = false;//跳出循环 return; } synchronized(this){ try { Thread.sleep(500);//模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } } }
二、S02E179_01线程同步与锁定2_synchronized_单例模式_doubleChecking
package com.test.thread.syn; /** * 单例设计模式:外部使用时确保一个类只有一个对象(内部创建,外部不能创建,只能使用) */ public class Singleton { public static void main(String[] args) { JvmThread thread1 = new JvmThread(100); JvmThread thread2 = new JvmThread(100); thread1.start(); thread2.start(); } } class JvmThread extends Thread{ private long time; public JvmThread(){ } public JvmThread(long time){ this.time = time; } @Override public void run(){ System.out.println(Thread.currentThread().getName()+"-->"+Jvm.getInstance(time)); } } /** * 单例设计模式 * 外部使用时确保一个类只有一个对象(内部创建,外部不能创建,只能使用) * 懒汉式 double checking * 1、构造器私有化,避免外部直接创建对象 * 2、声明一个私有的静态变量 * 3、创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象 */ class Jvm{ //声明一个私有的静态变量 private static Jvm instance = null;//懒得创建对象 //构造器私有化,避免外部直接创建对象 private Jvm(){ } //创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象 //一、不同步,产生多个对象 public static Jvm getInstance1(long time){ if(null==instance){ try { Thread.sleep(time);//延时,放大发生错误的概率 } catch (InterruptedException e) { e.printStackTrace(); } instance = new Jvm(); } return instance; } //二、加入synchronized,成为同步方法,只有一个对象 public static synchronized Jvm getInstance2(long time){ if(null==instance){ try { Thread.sleep(time);//延时,放大发生错误的概率 } catch (InterruptedException e) { e.printStackTrace(); } instance = new Jvm(); } return instance; } //三、同步块,只有一个对象,效率不高,存在对象也需要等待 public static Jvm getInstance3(long time){ //a、b、c、d线程进来都需要等待,效率不高,存在对象也需要等待 synchronized(Jvm.class){//锁住类的字节码信息 if(null==instance){ try { Thread.sleep(time);//延时,放大发生错误的概率 } catch (InterruptedException e) { e.printStackTrace(); } instance = new Jvm(); } return instance; } } //四、同步块,只有一个对象,doubleChecking提高已经存在对象的访问效率 public static Jvm getInstance(long time){ //第二段:后来c、d线程都进来判断,发现有对象,直接返回,不用等待 if(null==instance){ //第一段:刚开始a、b线程都进来等待,a进入创建对象后,b再进入后发现有对象就直接返回 synchronized(Jvm.class){//锁住类的字节码信息 if(null==instance){ try { Thread.sleep(time);//延时,放大发生错误的概率 } catch (InterruptedException e) { e.printStackTrace(); } instance = new Jvm(); } } } return instance; } }
package com.test.thread.syn; /** * 单例创建的方式 * 1、懒汉式 * 1)构造器私有化 * 2)声明私有的静态属性 * 3)对外提供访问属性的静态方法,确保该对象存在 */ public class MyJvm { private static MyJvm instance; private MyJvm(){ } public static MyJvm getInstance(){ if(null==instance){//提高效率 synchronized(MyJvm.class){ if(null==instance){//安全 instance = new MyJvm(); } } } return instance; } } /** * 饿汉式 * 1)构造器私有化 * 2)声明私有的静态属性,同时创建该对象 * 3)对外提供访问属性的静态方法,确保该对象存在 */ class MyJvm2 { private static MyJvm2 instance = new MyJvm2(); private MyJvm2(){ } public static MyJvm2 getInstance(){ return instance; } } /** * 类在使用时加载,延缓加载时机,提高效率 */ class MyJvm3 { private static class JvmHolder{//内部类,使用时加载 private static MyJvm3 instance = new MyJvm3(); } private MyJvm3(){ } public static MyJvm3 getInstance(){ return JvmHolder.instance; } }
相关文章推荐
- 深入学习Java中的字符串,代码点和代码单元
- Java中this关键字的使用
- 2015年底Google停止对eclipse的adt更新,转由eclipse团体提供
- java编译脚本的进阶之路
- Windows下Android+NDK开发环境搭建(JDK[8u45]+Eclipse+Android SDK[r24.1.2]+ADT+NDK[r10d])
- SpringMVC接收json数据的demo
- java_69_annotation
- webuploader + springmvc上传
- 【JAVA Web】spring mvc4.1.6 + spring4.1.6 + hibernate4.3.11 + mysql5.5.25 开发环境搭建及相关说明
- 高级特性(8)- JavaBean构件
- mac下配置maven失败
- 5 Tips for Reducing Your Java Garbage Collection Overhead
- SpringMVC接收json数据中的一些问题(415错误的解决)
- 【源】从零自学Hadoop(07):Eclipse插件
- Java编程思想
- Java数据类型和MySql数据类型对照表
- 1.24 Java周末总结 ①乘法数据的溢出 ②测试random随机数几率是否相等 ③判断字符串是否为纯数字
- java.time时间/日期API
- Java 基础——类的加载
- 【java】POJO 与javaBean(普通bean和EJB)