学习笔记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();
          }
      }
      

相关推荐

  1. 【网络基础】网络基础知识学习笔记

    2023-12-05 19:42:05       40 阅读
  2. juc并发线程学习笔记(一)

    2023-12-05 19:42:05       28 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-05 19:42:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-05 19:42:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-05 19:42:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-05 19:42:05       20 阅读

热门阅读

  1. 【LeetCode周赛】LeetCode第374场周赛

    2023-12-05 19:42:05       39 阅读
  2. 分享一波chatgpt的常用prompt

    2023-12-05 19:42:05       28 阅读
  3. dockerfile的面试题

    2023-12-05 19:42:05       36 阅读
  4. 备忘录模式-C++实现

    2023-12-05 19:42:05       38 阅读
  5. Oracle行转列,列转行使用实例

    2023-12-05 19:42:05       31 阅读
  6. docker 切换镜像源

    2023-12-05 19:42:05       32 阅读
  7. 前端实现token无感刷新的原因和步骤

    2023-12-05 19:42:05       36 阅读
  8. LeetCode刷题笔记第71题:简化路径

    2023-12-05 19:42:05       29 阅读
  9. sql 条件统计,count+if+sum

    2023-12-05 19:42:05       34 阅读
  10. 解析sql的数据流向关系获取

    2023-12-05 19:42:05       23 阅读