Thread 入门学习

Thread 线程创建

  1. extends Thread (继承线程类)

    • class Demo extends Thread {
          public void run (){
              //运行主体
          }
          
          public static void main (String[] args){
              new Demo.start();
          }
      }
      
    • 优点:敏捷,不需要代理类运行

    • 缺点:类只能单一继承,会占用继承

  2. implements Runnable (实现接口)

    • class Demo implements Runnable {
          public void run (){
              //运行主体
          }
          
          public static void main (String[] args){
              Thread thread = new Thread(new Demo());
              thread.start();
          }
      }
      
    • 优点:不占用继承

    • 缺点:需要代理类包装

  3. implements Callable(实现接口)

    • class Demo implements Callable {
          public Boolean call (){
              //运行主体
              return true;
          }
          
          public static void main (String[] args) throws ExecutionException,InterruptedException {
              //创建执行服务
              ExecutorService ser = Executors.new FixedThreadPool(1);
              
              //提交线程
              Future<Boolean> result = ser.sumbit(new Demo());
              
              //获取结果
              Boolean b = result.get();
              
              //关闭服务
              ser.shutdownNow();
              
          }
      }
      
    • 功能:带返回值,会抛出异常


Thread 线程状态

  • 五种基础状态
    • 新建状态
    • 可运行状态
    • 运行状态
    • 阻塞状态
    • 死亡状态

Thread 线程状态切换方法

  • Thread 入门学习

守护线程 (Daemon)

  • 虚拟机内运行的线程都死亡,守护线程会最后再死亡,无论线程内部是否是死循环

  • Thread thread = new Thread();
    //设置该线程为守护线程
    thread.setDaemon(true);
    

Thread 同步(Synchronized)

  • 目的:为了解决线程不安全的问题

  • 方法:

    • 方法添加 synchronized 修饰符

      • public synchronized void run (){}
        
      • 该同步会锁定方法所在的类或class,this对象

    • 代码块添加 synchronized 修饰符

      • public void run (){
            synchronized(需要锁定的对象){
                //代码块实现
            }
        }
        

Lock 锁 (reentrantlock 可重入锁定)

  • 目的:跟同步一样,也是为了解决线程不安全的问题,不过比起同步的解决办法,Lock锁性能损耗更小,使用更灵活

  • ReentrantLock lock = new ReentrantLock();
    //在加锁解锁之间的代码,被锁定操作
    try {
        //加锁
        lock.lock();
    } catch (Exception e){
        //捕获异常
    } finally {
        //解锁
        lock.unlock();
    }
    
  • ?


死锁

  • 简而言之,某个代码块同时拥有”两个以上对象的锁“时,就可能发生死锁的问题
  • 造成死锁的四个必要条件:
    • 互斥条件:一个资源每次只能被一个进程使用。
    • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    • 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
    • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

线程通信方法

  • 理解:线程与线程之间,为了达成之间运行的条件,需要与另一个线程进行通信处理

    • 如:生产者与消费者案例,生产多少消费多少
  • 解决方法

    1. 管程法(利用容器作为条件)

    2. 信号灯法(利用布尔值作为条件)

      //定义一个容器 ,用数组或者集合实现都可以
      Int[] array = new Int[10];
      //定义一个信号灯
      Boolean flag = false;
      public synchronized void run (){
          //满足条件就等待 以上方法二选一作为条件判断
          if(flag){
              //wait方法会释放锁,等待的线程会回到锁池状态
          	this.wait();
          }
          //不满足就唤醒其余所有线程
          this.notifyAll();
      }
      

线程池

  • 背景:经常创建和销毁线程、使用量特别大的资源,比如并发的情况下的线程,对性能影响很大 (线程一旦死亡,不能再启动)

  • 思路:提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中,避免了频繁创建销毁,实现重复利用

  • 用法:使用 ExecutorService 工具类创建

    • ExecutorService ser = new FixedThreadPool(4);
      //执行线程
      ser.execute(new Thread());
      ser.execute(new Thread());
      ser.execute(new Thread());
      ser.execute(new Thread());
      
      //关闭服务
      ser.shutdown();
      

Thread 入门学习

上一篇:浅谈如何使用clang替换gcc进行编译


下一篇:Docker的常用命令总结