标签:不能 bsp 变量 过程 sync cto 安全 互斥 正在执行
什么是线程?
多线程应用场景:
    1、Java程序运行原理
        Java命令会启动Java虚拟机,启动jvm,等于启动了一个应用程序(进程)。
        该进程会启动了一个主线程,然后主线程去调用某个类的main方法
    2、jvm的启动是多线程的吗?
        JVM开启至少启动了垃圾回收线程和主线程,所以是多线程的
        多次启动一个线程是非法的
    
    方式一:继承Thread类
      1、继承Thread类,Override:run方法
      2、把新线程要做的事情写在run方法中
      3、创建线程对象
      4、执行start方法,启动新线程  
    方式二: 实现Runnable接口(建议使用,后期扩展性强)
       1、定义一个类实现Runnable接口
       2、重写run方法 
       3、new一个Thread对象,利用Thread类的构造,将Runnable的子类对象当作参数传进去
       4、 执行Thread.start(),开启线程  
       
  原理(查看源码):
       1、Thread实现了Runnable接口,通过Thread的构造函数,传递了Runnable接口的引用target(目标,靶子)
       2、通过Thread类的init方法,将传入引用target赋给成员变量target 
       3、在Thread类的run方法中,如果target不为空,则线程开启时(start())会调用Runnable接口子类对象的run方法
    
      两种方式的区别:
      a:继承Thread:由于子类重写了Thread类的run方法,当调用start()时,直接找到子类的run方法
      b : 实现Runnable:Thread类的构造函数中传入了Runnable的引用,通过init方法将引用赋给了Runnable类型的成员变量target
                      在启动线程时,start方法调用run方法,在run方法里,判断target不为空的话,则调用target的run方法,  执行子类重写的run方法
      
      两种方式的好处和弊端:
      继承Thread:  
               好处是:可以直接调用Thread类的方法,代码简单
               弊端是:如果已经有了父类,则不能用这种方法,java单继承,多实现
      实现Runnable
               好处: 由于java单继承多实现,即使线程类有了父类也可以实现接口。
               弊端:不能直接使用Thread中的方法,需要先获取线程对象,再通过Thread的构造传入,代码复杂  
      
      匿名内部类实现线程的两种的方式:
        1、new Thread(){ @override public void run();    }.start();
        2、new Thread(new Runnable(){ @override public void run();}){}.start();
     1、默认: Thread.getName(): 默认Thread-序号(从1开始)      
     2、构造:Thread(String name):构造命名 name
     3、设置:this.setName(String name):      
     
     Thread.currentThread()
     
   
    Thread.sleep(毫秒,微妙),控制当前线程休眠若干时间  1秒:1000毫秒:1000微妙:1000纳秒  1秒=10亿纳秒
        
      Thread.setDaemon(boolean on)将该线程标记为守护线程或用户线程。    
       该线程不会单独执行,当其他的非守护线程都执行结束后,自动退出
       比如QQ聊天,把QQ退出,聊天界面也会关闭,聊天界面可以理解为守护线程
  
    join,当前线程暂停,等待指定的线程执行结束以后,当前线程再继续
    join(int),插队,等待指定的毫秒之后,两条线程交替执行         
   
     yield让出cpu  
 
     setProperties()设置线程优先级 ,最小是1,最大是10,默认是5
    
     1、什么情况下需要同步
          当多线程并发、有多段代码同时执行时,我们希望某一段代码执行的过程中不要切换到其他线程工作。 这时就需要同步。
          如果两段代码是同步的,那么同一时间只能执行一段,在一段代码没执行结束之前,不会执行另一段代码。
     2、同步代码块
          使用synchronized关键字加上一个锁对象来定义一段代码,这就叫同步代码块。
          多个同步代码块如果使用相同的锁对象,那么他就是同步的。
          锁对象是任意的,但不能是匿名对象,匿名对象不是同一个对象
          同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
        
如何保证锁是一致的?
     对于继承Thread方式:
               在方法上加synchronized关键字
               对于静态方法,锁对象是this
               对于非静态方法,锁对象是当前类的字节码对象   
     对于实现Runnable接口方式:
                锁对象可以是this,因为只创建了一个Runnable引用对象传进Thread的构造
                     
         多个线程相互等待
         避免同步代码块的嵌套
       
         看源码:Vector、StringBuffer、HashTable、Collection.synchronized(xxx)
         Vector是线程安全的,ArrayList是线程不安全的
         StringBuffer是线程安全的,StringBuilder是线程不安全的
         HashTable是线程安全的,HashMap是线程不安全的
         Collection.synchronized(xxx):返回线程安全的集合
               
    
       单例设计模式:保证类在内存中只有一个对象
       
      如何保证类在内存中只有一个对象?
     1、控制类的创建,不让其他类类创建本类的对象
     2、在本类中定义一个本类的对象
     3、提供公共的访问方式  
       
        单例设计模式的两种写法:
        饿汉式:      
        private Singleton(){  }
        //创建本类对象,私有化,相当于成员变量
        private static Singleton s = new Singleton();
        //对外提供一个公共的访问方式
        public static Singleton getInstance(){
        return s;
    }
        懒汉式:
    private Singleton(){  }
    private static Singleton s;
    public static Singleton getInstance(){
        if(s==null){
            //线程1等待,线程2等待,线程1执行,线程2执行,有可能造成2次对象的情况
            s = new Singleton();
        }
        return s;
    }
 
   其他写法:
    private Singleton(){  }
    //创建本类对象,私有化,相当于成员变量
    private static Singleton s = new Singleton();
    //对外提供一个公共的访问方式
    public static Singleton getInstance(){
    return s;
    }
    饿汉式和懒汉式的区别:
    1 饿汉式是空间换时间(一上来就创建对象),懒汉式是时间换空间(需要判断,浪费时间)
    2 在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能创建多个对象(如果判断的时候产生线程等待)
    
       
    Runtime类是一个单例类,查看源码发现构造方法私有,并且是饿汉式的单例形式
    r.exec("shutdown -s -t 300")://5分钟之后关机
     
     Timer.schedule(task, delay):在指定的时间做指定的事情
     Timer.schedule(task, delay, period);period之后再做同样的事情,比如闹钟
    
    1、什么时候需要通信
    多个线程并发执行时,在默认的情况下CPU是随机切换线程的
    如果我们希望他们有规律的执行,就可以使用通信,例如每个线程执行一次打印
    2、怎么通信
    线程等待 wait(),同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
    线程唤醒,notify(),notifyAll();
    这两个方法必须在同步代码块中执行,并且使用同步锁对象来调用
        
  
    为什么wait和notify方法定义在Object类中?
               因为锁对象可以使任意对象,Object是所有类的基类,所以需要这么定义
    sleep和wait的区别?
       (a)sleep在Thread类中,需要传入参数,就是时间,时间到了就醒来
       wait在Object类中,方法可以传入参数,也可以不传入参数 ,传入参数则在参数时间后等待,不传则直接等待
           传参时。sleep睡一阵子就起来,wait一阵子之后就睡    
       (b)slepp在同步函数或者同步代码块中不释放锁(睡着了也抱着锁)    
        wait在同步函数或这同步代码块中释放锁      
        
    
     1.同步,使用ReenTrantLock类的lock()和unlock()方法进行同步
            lock()获取锁,unlock()释放锁
     2.通信,
                             使用ReenTrantLock类的newCondition()方法获取Condition对象
                             需要等待的时候使用Condition的await()方法,唤醒的时候用signal()方法
                             不同的线程使用不同的condition,这样就能区分唤醒的时候找哪个线程了
     3.常用方法:
         ReenTrantLock.lock():获得锁                      
         ReenTrantLock.unlock():释放锁                      
         ReenTrantLock.await():等待                                                
         ReenTrantLock.signal():唤醒                      
     
 
       线程组概述:
       Java中使用ThreadGroup来表示线程组,对一批线程进行分类管理,java允许程序直接对线程组进行控制
           默认情况下,所有现场都属于主线程组
           我们也可以给线程设置分组                        
         
        新建:创建线程对象[thread、runnable]
        就绪:线程对象已经启动,但没有获得CPU执行权[start()]
        运行:获取到了CPU执行权[抢到了CPU执行权]
        阻塞:没有CPU的执行权,回到就绪[sleep()、wait()]
        死亡:代码运行完毕,线程消亡,变成垃圾  [run()结束、stop(方法过时)]
        
 

       简单工厂模式:
           又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
       优点:
        客户端不需要负责对象的创建,从而明确了每个类的职责
       缺点:
       这个静态工厂类负责所有对象的创建,如果有对象添加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期维护
       
              
       工厂方法模式概述:
         抽象工厂类定义创建对象的接口,具体对象的创建工作由抽象工厂类的各个实现类来完成
       优点:
         客户端不需要负责对象的创建,明确了个各类的职责,如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可
        不影响已有代码,便于后期维护,增强了系统的扩展性
       缺点:
        需要额外的编写代码,增加了工作量         
   
标签:不能 bsp 变量 过程 sync cto 安全 互斥 正在执行
原文地址:https://www.cnblogs.com/ltfxy/p/10203302.html