Thread知识

1.基础知识

1.sleep()的作用是在指定的毫秒数内让当前"正在执行的线程"休眠.
2.getId()获取线程的唯一标识
3.停止线程3种方法

- 使用退出标志,正常退出
- 使用stop强行终止线程,已废弃.(他会抛出一个ThreadDeath异常.不需要捕获)
- 使用interrupt中断线程,他不会立即停止线程,而是加一个停止的标记.(在线程中捕获这个标记.进行主动退出)
- 使用抛出异常.try-catch停止线程

4.静态方法 interrupted()返回当前正在运行的线程是否已经中断.,在哪个线程里调就返回哪个线程的中断状态
线程的方法 isInterrupted()返回调用线程是否已经中断,哪个线程对象调用他,他返回哪个线程的中断状态.
5.suspend()方法暂定线程 resume()方法恢复线程,缺点是会占有公共对象的锁和数据不同步
6.yield()使当前线程放弃当前的CPU资源,但放弃时间不确定,有可能刚放弃马上又获得CPU时间片.
7.线程优先级 1-10 , 10最高.优先级高得到的CPU资源较多.但不是绝对的.优先级具有继承性,如A线程启动B线程.则B线程的优先级和A相同.
8.守护线程,是特殊的线程.当进程中不存在非守护线程时,守护线程自动销毁. gc就是守护线程.
9.synchronized 关键字取得的就是对象锁.而一个对象只有一把锁.当一个线程获得一个对象的锁后.可以直接访问他所有的带锁的方法.称为锁的重入机制.可重入锁也支持父子类继承的环境中.既子类拿到对象锁后.可以访问父类的带锁的方法.
10.一个线程执行的代码出现异常时,其所持有的锁会自动释放.
11.锁不能被继承.既父类的同步方法加了锁.在子类重写后却没加锁,那么子类方法不会继承父类的锁.因为锁是针对对象的.创建子类对象时不会创建父类对象.也就不涉及父类对象的锁的方法.
12.同步代码快.可以减少同步等待的时间.不再同步代码块中的代码是异步执行,同步代码块中的代码同步执行.同步代码块也是锁定某个对象的.
13.synchronized关键字加到static方法上是给Class类上锁,而synchronized关键字加到非static静态方法上是给对象加锁.而String具有常量池.不建议对String 加锁.
14.volatile关键字.使变量在多个线程间可见.

Thread知识_第1张图片
1.png

  • volatile关键字强制从公共内存中读取变量的值.而不使用每个线程的工作内存.
  • volatile增加了实例变量在多个线程之间的可见性
  • volatile是线程同步的轻量级实现,效率比synchronized高并且volatile只能修饰变量
  • 多线程访问volatile不会发送阻塞,而访问synchronized会出现阻塞
  • volatile能保证数据的可见性,但不保证原子性(原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行)而synchronized可保证原子性,继而保证可见性
  • volatile解决的是变量在多个线程的可见性,synchronized解决的是多个线程访问资源的同步性(个人理解volatile用来读值比较好.写的话会数据错乱,并不能保证同步性.)
    15.wait/notify方法在调用前线程必须持有对象锁,这两个方法属于object.wait调用后会释放锁.notify方法执行后,当前线程要把同步方法执行完才会释放锁.之后wait的线程被唤醒,拿到对象锁.如果某线程wait后没有其他线程调用notify.则这个线程会一直等待下去.即时对象锁已经被释放. notifyAll唤醒全部wait的线程.
    16 执行完同步代码块会释放锁.执行同步代码块过程中如果遇到异常终止,会释放锁.执行锁对象的wait方法会释放锁.notify方法一次会随机唤醒一个wait方法.
    17.通过管道进行线程间通信,可以通过字节流,字符流.
    pipeStream (管道流)用于在不同线程间直接发送数据,一个线程发送数据到管道,另一个线程从管道中读取数据.
    18.join的作用是等待线程对象销毁.Z线程中调用X.join使所属线程对象X正常执run()方法,而使当前线程Z进行无限期的阻塞,等待线程X销毁后在继续执行Z后面的代码.
    join在内部是使用wait方法实现,所以会释放锁.而sleep不会释放锁.
    join过程中调用interrupt会抛出异常.
    19.threadLocal可以为每个线程单独设置自己的值.inheritableThreadLocal可以让子线程从父线程中取得父线程继承下来的值.
    20.ReentrantLock类,用来实现同步功能,支持获得锁,释放锁.
lock.lock() 获得锁  lock.unlock() 释放锁
Condition 是在一个Lock对象里面创建多个Condition(对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知
在调度上更加灵活.既可以唤醒指定线程
Condition的wait,sign方法需要在Lock.lock后调用.
公平锁.线程获取锁的顺序是根据线程枷锁的顺序来分配的,非公平锁,线程获得锁是随机的.ReentrantLock构造函数可以传boolean表示公平锁还是非公平锁
getHoleCount()返回当前线程保持次锁定的个数,也就是调用lock方法的次数.
getQueueLength() 返回等待获取锁的线程的个数.
getWaitQueueLength(Condition condi) 返回等待condition的wait的线程数. 
tryLock() 仅在锁未被另一个线程保持时,才获取该锁.
awaitUntil(mills) 在等待mills的到期时间前可以被唤醒.不必非要等待mills长的时间

21.ReenTrantReadWriteLock读写锁
读写锁分为两个锁.读锁,称为共享锁. 写锁,称为排它锁.多个写锁或者多个读锁加写锁互斥.既可以多线程读.只能单线程写.
22.单例模式与多线程结合
1.恶汉模式,静态变量直接创建对象.然后返回
2.懒汉模式.在调用时返回.正规写法是双检查机制

Thread知识_第2张图片
1.png

3.私有的静态内部类创建外部类对象.提供方法返回外部类对象.

Thread知识_第3张图片
1.png

4.序列化|反序列化单例对象时,需要重写 readResolve方法返回单例对象
5.静态代码块创建单例对象.

Thread知识_第4张图片
1.png

6.枚举实现单例模式.(使用枚举类时,构造方法被自动调用,在枚举的构造方法中创建单例类的单例对象)
23.线程的状态
-new 至今尚未启动(创建后还没start)
-runnable 正在java虚拟机中执行(可能获得了CPU时间片,也可能没获得CPU时间片)
-blocked 受阻塞并等待某个锁

-waiting      无限期的等待另一个线程来执行某一特定操作
-timewaitting    在指定时间内等待另一线程执行某一特定操作
-terminated    已退出的线程
Thread知识_第5张图片
1.png

1.单例模式的写发

所有的单例模式都是构造函数私有化.成员以private static 修饰,提供公开static 方法访问.不让别人实例化他,

1.恶汉模式.就是加载类时候就加载,缺点是不能有其他实例变量,因为getInstance无法同步.
如果从始至终从未使用过这个实例,则会造成内存的浪费
  public class A{ 
    private static A obj =new A(); //直接实例化
     也可以使用静态代码块
    private static A obj;
    static {
      obj=new A();
    }
    private A(){}
    public static A getInstance(){
      return obj;
    }
  }

2.懒汉模式.调用时候加载,单线程的时候没事.多线程会产生多个obj对象.
 public class A{
    private static A obj;
    private A(){}
    public static A getInstance(){
      if(obj ==null){
        //初始化东西
        obj =new A();
      }
        return obj;
    }
  }
3.懒汉模式加 synchronized 关键字. 方法加锁.导致方法需要等待某线程执行完才释放锁.方法执行效率低.
public class A{
  private static A obj;
  private A(){}
  sychnorized public static A getInstance(){ 
      if(obj ==null){
      obj =new A();
      }
      return obj;
  }
}
4.另一种懒汉模式加锁.其实和3是一样的
public class A{
  private static A obj;
  private A(){}
  
  public static A getInstance(){
    synchronized(A.class){  //锁住类对象,同时代码块锁要在 obj判断外边.不然没意义.
         if(obj ==null){
            obj =new A();
         }
    }
    return obj;
   }
}
 5.懒汉模式加dcl(doublc check lock) 双检查锁机制
    public class A {
      private volatile static A obj;   volatile关键字使所有线程强制去主存储区拿obj变量.
      private A () {}
      public static A getInstance(){
        if(obj ==null){
              //这里可以进行一些线程无关的初始化,保证不需要同步的代码异步执行
              synchronized(A.class){   
                   if( obj ==null){ //这里判空是为如果有线程阻塞,先前进来的已经创建完毕,就不需要在创建了.
                      obj=new A();
                    }
              }
       }
        return  obj;
      }
    }
6.使用静态内部类, 不需要外部类的引用,效果同双检查锁
采用了类装载的机制来保证初始化实例时只有一个线程,
内部类是延时加载的,也就是说只会在第一次调用时加载。不调用就不加载
  public class A{
    private A(){}
    private static class B{
        private static A obj =new Object();
    }
    public static A getInstance{
        return B.obj;
    }
  }
7.枚举方式,在使用枚举时,构造方法被自动调用.不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,
每一个枚举类型和定义的枚举变量在JVM中都是唯一的
  public class B{
    public enum C{
       factory;  //枚举类型
       private A obj; //需要初始化的参数
        private C{  //枚举的构造函数会在调用枚举类型时候执行.
            obj =new A();
        }
        public  A getA(){
            return obl;
        }
    }
    public static A getInstance(){
      return B.factory.getA();
     }
  }
  8.单例模式在序列化时.重新读取会生成新的对象.解决方法如下
public class A {
  private staitc A obj =new A();
  protected A(){}

  /反序列时直接返回当前INSTANCE
   private Object readResolve() {     //重写这个方法.返回之前创建的
            return INSTANCE;     
      }    
}




你可能感兴趣的:(Thread知识)