学习笔记8——JUC入门基础知识

学习笔记系列开头惯例发布一些寻亲消息

链接:https://baobeihuijia.com/bbhj/contents/3/199561.html

  • 进程和线程:进程是资源分配的最小单位,线程是CPU调度的最小单位

  • 并行和并发(从cpu的角度划分)

    • 并发:任务调度器使得CPU在同一段时间执行不同的任务,微观串行,宏观并行
    • 并行:在同一时刻cpu做多件事情的能力
  • 异步同步(从方法的角度划分)

    • 方法的执行需要等待别的结果返回,就是同步
    • 不需要等待别的方法结果返回,就是异步
  • 三种方法创建线程

    # 方法一
    Thread t = new Thread(){
    	public void run(){
    		xxxxx;
    	}
    };
    t.setName("t1")
    t.start();
    
    # 方法二
    Runnable r = new Runnable(){
    	public void run(){
    		xxxxxx;
    	}
    }
    Thread t = new Thread(r,"t2")
    t.start();
    
    # 方法三:简化lambda
    Runnable t = ()->{xxxxx;};
    Thread t = new Thread(r,"t2")
    t.start();
    
    # FutureTask是带有返回值的Runnable
    
    # windows
    tasklist 查看所有进程
    jps 显示所有的java进程
    taskkill 杀死某个进程
    
    # linux
    ps -fe 查看所有的命令进程
    ps -fe | grep java   筛选带有Java的
    jps 列出java进程
    kill 4202  杀死进程
    top 查看进程信息
    top -H -p 4262 查看该进程的线程信息
    jstack 4262 查看某个时刻的线程信息
    
  • 字节码放到方法区(二进制格式)

  • jvm启动main线程,并分配main栈帧

  • 线程上下文切换:cpu不再执行当前线程,转而执行另一个线程代码
    • 线程的cpu时间片用完
    • 垃圾回收
    • 有更高优先级的线程
    • 线程自己调用sleep,yield,wait,join,park,synchronized,lock方法
  • context switch的时候,需要操作系统保存当前线程的状态,包括:
    • 程序计数器、虚拟机栈中每个栈帧的信息(局部变量、操作数栈、返回地址)
  • 知识点

    • start 和 run 的区别(start是由别的线程调用从而启动A线程的,调用后不会影响该线程的本身进度,run是由线程A分配到cpu后才执行的)

    • sleep和yield

      • sleep就是放弃了cpu的使用,进入TIMED_WAITING阻塞状态
      • yield:让线程从RUNNABLE变为RUNNABLE 就绪状态
      • 在哪个线程下写 thread.sleep就是休眠哪个线程
      • 状态: NEW --- RUNNABLE(可以被cpu调用的) --- TIMED_WAITING (休眠)
      • 区别:cpu仍然会考虑yield,但是不会考虑sleep
    • 线程优先级setPriority:只是一个提示,调度器可以忽略这个信号

    • join:等待线程运行结束,哪个线程调用就等待哪个线程

    • join(时间):等待 min(时间,线程执行时间)

    • interrupt

      • 打断阻塞状态:sleep wait join 这些打断后isInterrupted重新置为false(打断后不能立即查看,需要等打断进入到异常块才能看到重置为false)

        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                log.debug("sleep...");
                try {
                    Thread.sleep(5000); // wait, join
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },"t1");
        
            t1.start();
            Thread.sleep(1000);
            log.debug("interrupt");
            t1.interrupt();
            // 这里如果没有等,可能还没有等t1重置为false就打印出true
            Thread.sleep(1000);
            log.debug("打断标记:{}", t1.isInterrupted());
        }
        
      • 打断正常状态:isInterrupted置为true,但是线程不会结束,需要自己再去判断是否真的要停止,获得currentThread(). isInterrupted 判断是否为true

        @Slf4j(topic = "c.Test12")
        public class Test12 {
        
            public static void main(String[] args) throws InterruptedException {
                Thread t1 = new Thread(() -> {
                    while(true) {
                        boolean interrupted = Thread.currentThread().isInterrupted();
                        // 没有判断的话就一直不会停止
                        if(interrupted) {
                            log.debug("被打断了, 退出循环");
                            break;
                        }
                    }
                }, "t1");
                t1.start();
        
                Thread.sleep(1000);
                log.debug("interrupt");
                t1.interrupt();
            }
        }
        
    • 两阶段终止模式(A线程如何优雅的停止B线程)

      ```
      @Slf4j(topic = "c.TwoPhaseTermination")
      class TwoPhaseTermination {
          // 监控线程
          private Thread monitorThread;
          // 停止标记
          private volatile boolean stop = false;
          // 判断是否执行过 start 方法
          private boolean starting = false;
      
          // 启动监控线程
          public void start() {
              synchronized (this) {
                  if (starting) { // false
                      return;
                  }
                  starting = true;
              }
              monitorThread = new Thread(() -> {
                  while (true) {
                      Thread current = Thread.currentThread();
                      // 是否被打断
                      if (stop) {
                          log.debug("料理后事");
                          break;
                      }
                      try {
                          Thread.sleep(1000);
                          log.debug("执行监控记录");
                      } catch (InterruptedException e) {
                      }
                  }
              }, "monitor");
              monitorThread.start();
          }
      
          // 停止监控线程
          public void stop() {
              stop = true;
              monitorThread.interrupt();
          }
      }
      ```
      
    • park:代码会停止在执行park()的这一行,遇到interrupt后才会继续(标记为true),且以后再遇到park也不会停止,除非再次重置为false

    • 不推荐用的:

      • stop:强制让线程停止,即线程的资源可能还未被释放
      • suspend:挂起线程
      • resume 恢复线程运行
    • 主线程和守护线程:只要其他非守护线程结束,那么即使守护线程没有运行结束,也会停止运行(垃圾回收线程)

      t1.setDaemon(true); //设置守护线程
      
    • 线程的状态(操作系统层面)

      • 初始状态:仅语言层面创建线程对象,与操作系统未关联
      • 可运行状态:cpu可以调度
      • 运行状态:获取了cpu时间片
      • 阻塞:
      • 终止状态
    • 线程六种状态(java层面)

      • 初始状态:new但是尚未start

      • RUNNABLE:start之后线程的运行状态,可运行状态,阻塞状态

      • BLOCKED:拿不到锁

      • WAITING:join

      • TIMED_WAITING:sleep

      • TERMINATED:终止

        package cn.itcast.n3;

        import lombok.extern.slf4j.Slf4j;

        import java.io.IOException;

        @Slf4j(topic = "c.TestState")
        public class TestState {
        public static void main(String[] args) throws IOException {
        Thread t1 = new Thread("t1") {
        @Override
        public void run() {
        log.debug("running...");
        }
        };

              Thread t2 = new Thread("t2") {
                  @Override
                  public void run() {
                      while(true) { // runnable
        
                      }
                  }
              };
              t2.start();
        
              Thread t3 = new Thread("t3") {
                  @Override
                  public void run() {
                      log.debug("running...");
                  }
              };
              t3.start();
        
              Thread t4 = new Thread("t4") {
                  @Override
                  public void run() {
                      synchronized (TestState.class) {
                          try {
                              Thread.sleep(1000000); // timed_waiting
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  }
              };
              t4.start();
        
              Thread t5 = new Thread("t5") {
                  @Override
                  public void run() {
                      try {
                          t2.join(); // waiting
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              };
              t5.start();
        
              Thread t6 = new Thread("t6") {
                  @Override
                  public void run() {
                      synchronized (TestState.class) { // blocked
                          try {
                              Thread.sleep(1000000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  }
              };
              t6.start();
        
              try {
                  Thread.sleep(500);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              log.debug("t1 state {}", t1.getState());
              log.debug("t2 state {}", t2.getState());
              log.debug("t3 state {}", t3.getState());
              log.debug("t4 state {}", t4.getState());
              log.debug("t5 state {}", t5.getState());
              log.debug("t6 state {}", t6.getState());
              System.in.read();
          }
        

        }

相关推荐
考试宝几秒前
国家宠物美容师职业技能等级评价(高级)理论考试题
经验分享·笔记·职场和发展·学习方法·业界资讯·宠物
黑叶白树2 小时前
简单的签到程序 python笔记
笔记·python
@小博的博客2 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
幸运超级加倍~3 小时前
软件设计师-上午题-15 计算机网络(5分)
笔记·计算机网络
南宫生3 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步3 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
love_and_hope4 小时前
Pytorch学习--神经网络--搭建小实战(手撕CIFAR 10 model structure)和 Sequential 的使用
人工智能·pytorch·python·深度学习·学习
Chef_Chen4 小时前
从0开始学习机器学习--Day14--如何优化神经网络的代价函数
神经网络·学习·机器学习
芊寻(嵌入式)4 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
准橙考典4 小时前
怎么能更好的通过驾考呢?
人工智能·笔记·自动驾驶·汽车·学习方法