day31-线程基础01

打印 上一主题 下一主题

主题 872|帖子 872|积分 2618

线程基础01

1.程序 进程 线程


  • 程序(program):是为完成的特定任务,用某种语言编写的一组指令的集合。简单来说,就是我们写的代码。


  • 进程:

    • 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。
    • 进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生、存在和消亡的过程。

  • 线程:

    • 线程是由进程创建的,是进程的一个实体
    • 一个进程可以有多个线程,比如:用迅雷同时下载多个文件

  • 其他相关概念:

    • 单线程:同一时刻,只允许执行一个线程
    • 多线程:同一时刻,可以执行多个线程,比如:一个qq进程,可以同时打开多个聊天窗口;一个迅雷进程,可以同时下载多个文件。
    • 并发:同一时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单地说,单核cpu实现的多任务就是并发

    • 并行:同一时刻,多个任务同时执行。多核cpu可以实现并行。在电脑中也可能同时出现并发和并行的状态。

例子:
  1. package li.thread;
  2. public class CpuNum {
  3.     public static void main(String[] args) {
  4.         Runtime runtime = Runtime.getRuntime();
  5.         //获取当前的电脑的cpu数量
  6.         int cpuNums = runtime.availableProcessors();
  7.         System.out.println("当前的CPU数量="+cpuNums);//当前的CPU数量=8
  8.     }
  9. }
复制代码
2.线程的基本使用


  • 创建线程的两种方式
在java中线程来使用有两种方法:

  • 继承Thread类,重写run方法
  • 实现Runnable接口,重写run方法
2.1继承Thread创建线程

例子1:线程应用案例1-继承Thread类
1)请编写程序,开启一个线程,该线程每隔一秒,在控制台输出 “喵喵,我是小猫咪”
2)对上题改进:当输出80次“喵喵,我是小猫咪”时,结束该线程
3)使用JConsole监控线程执行情况,并画出程序示意图
  1. package li.thread;
  2. //演示通过继承Thread类创建线程
  3. public class Thread01 {
  4.     public static void main(String[] args) throws InterruptedException {
  5.         
  6.         //创建一个Cat对象,可以当做线程来使用
  7.         Cat cat = new Cat();
  8.         
  9.         cat.start();//启动线程
  10.         
  11.         //当main线程启动一个子线程 Thread-0后,主线程不会阻塞,会继续执行
  12.         //这时 主线程和子线程是交替执行
  13.         System.out.println("主线程继续执行="+Thread.currentThread().getName());//主线程继续执行=main
  14.         for (int i = 0; i < 60; i++) {
  15.             System.out.println("主线程 i="+i);
  16.             //让主线程休眠
  17.             Thread.sleep(1000);
  18.         }
  19.     }
  20. }
  21. //1.当一个类继承了Thread类,该类就可以当做一个线程使用
  22. //2.我们会重写run方法,写上自己的业务代码
  23. //3.run Thread类实现了Runnable接口的run方法
  24. /*
  25.       @Override
  26.       public void run() {
  27.           if (target != null) {
  28.               target.run();
  29.           }
  30.       }
  31. */
  32. class Cat extends Thread {
  33.     @Override
  34.     public void run() {//重写run方法,写上自己的业务逻辑
  35.         int times = 0;
  36.         while (true) {
  37.             //该线程每隔1秒,在控制台输出 “喵喵,我是小猫咪”
  38.             System.out.println("喵喵,我是小猫咪" + (++times)+" 线程名称="+Thread.currentThread().getName());
  39.             //让该线程休眠一秒
  40.             try {
  41.                 Thread.sleep(1000);//单位为毫秒 try-catch快捷键:Ctrl+Alt+T
  42.             } catch (InterruptedException e) {
  43.                 e.printStackTrace();
  44.             }
  45.             if (times == 80) {
  46.                 break;//当times到80,退出while,这是线程也就退出了
  47.             }
  48.         }
  49.     }
  50. }
复制代码
3)使用JConsole监控线程执行情况,并画出程序示意图:
如下,在控制台点击run,运行程序,在程序运行时,点击Termial
在控制台输入JConsole,回车。
点击本地进程,点击Thread01,点击下方连接按钮:
在弹出窗口中点击不安全的连接按钮:
<img alt="image-20220903202109982" >在窗口中点击“线程”:
可以在左下角的线程小窗口中看到main线程和Thread-0线程在同时进行
等待一段时间,可以看到当run窗口的主线程 i = 60之后,main线程结束
结束前:
结束后:
当线程名称=Thread-0输出到80次时,虽然可以Thread-0还在左下角,但是实际上Thread-0线程已经结束了,整个进程随之结束。
程序示意图:

注意:在多线程编程里面,并不一定说主线程结束了,整个进行就结束了,等所有线程都结束了,进程才会结束。
2.2为什么是start?

在2.1的例子中,主方法中定义了cat对象,该对象调用了start方法,start方法会去启动一个线程,最终会执行Cat 类的run方法。
思考一个问题:既然最终都是要调用run方法,为什么cat对象还要通过start方法对调用run呢?为什么不直接调用?
答案: 首先通过 对象.run() 方法  可以执行方法,但是不是使用的多线程的方式,就是一个普通的方法,没有真正地启动一个线程。即这时候把run方法执行完毕,才能执行主方法剩下的语句。
如下图:将cat.start();改为cat.run();之后的运行结果:
在run方法执行完之后才执行主方法剩下的语句
那么在调用start方法时,整个过程到底是什么样子的?
点击start()方法:可以在start方法中看到一个start0()方法:
点击start0( )方法:可以看到start0是一个本地方法,由 JVM调用,底层是c/c++实现。
再看看run()方法的源码:可以看到run方法只是简单的调用了实现类的run,没有进行任何的多线程处理。
换而言之,Java中真正实现多线程的效果的是start0方法,而不是run方法


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

拉不拉稀肚拉稀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表