首页 > 其他分享 >day31-线程基础01

day31-线程基础01

时间:2022-09-03 22:12:58浏览次数:62  
标签:01 run Thread day31 start 线程 进程 方法

线程基础01

1.程序 进程 线程

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

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

    1. 线程是由进程创建的,是进程的一个实体
    2. 一个进程可以有多个线程,比如:用迅雷同时下载多个文件
  • 其他相关概念:

    1. 单线程:同一时刻,只允许执行一个线程
    2. 多线程:同一时刻,可以执行多个线程,比如:一个qq进程,可以同时打开多个聊天窗口;一个迅雷进程,可以同时下载多个文件。
    3. 并发:同一时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单地说,单核cpu实现的多任务就是并发
    image-20220903183757457
    1. 并行:同一时刻,多个任务同时执行。多核cpu可以实现并行。在电脑中也可能同时出现并发和并行的状态。
image-20220903183821311

例子:

package li.thread;

public class CpuNum {
    public static void main(String[] args) {

        Runtime runtime = Runtime.getRuntime();
        //获取当前的电脑的cpu数量
        int cpuNums = runtime.availableProcessors();
        System.out.println("当前的CPU数量="+cpuNums);//当前的CPU数量=8

    }
}

2.线程的基本使用

  • 创建线程的两种方式

在java中线程来使用有两种方法:

  1. 继承Thread类,重写run方法
  2. 实现Runnable接口,重写run方法
image-20220903191317462

2.1继承Thread创建线程

例子1:线程应用案例1-继承Thread类

1)请编写程序,开启一个线程,该线程每隔一秒,在控制台输出 “喵喵,我是小猫咪”

2)对上题改进:当输出80次“喵喵,我是小猫咪”时,结束该线程

3)使用JConsole监控线程执行情况,并画出程序示意图

package li.thread;

//演示通过继承Thread类创建线程
public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
        
        //创建一个Cat对象,可以当做线程来使用
        Cat cat = new Cat();
        
        cat.start();//启动线程
        
        //当main线程启动一个子线程 Thread-0后,主线程不会阻塞,会继续执行
        //这时 主线程和子线程是交替执行
        System.out.println("主线程继续执行="+Thread.currentThread().getName());//主线程继续执行=main
        for (int i = 0; i < 60; i++) {
            System.out.println("主线程 i="+i);
            //让主线程休眠
            Thread.sleep(1000);
        }
    }
}

//1.当一个类继承了Thread类,该类就可以当做一个线程使用
//2.我们会重写run方法,写上自己的业务代码
//3.run Thread类实现了Runnable接口的run方法
/*
      @Override
      public void run() {
          if (target != null) {
              target.run();
          }
      }
 */
class Cat extends Thread {
    @Override
    public void run() {//重写run方法,写上自己的业务逻辑
        int times = 0;
        while (true) {
            //该线程每隔1秒,在控制台输出 “喵喵,我是小猫咪”
            System.out.println("喵喵,我是小猫咪" + (++times)+" 线程名称="+Thread.currentThread().getName());
            //让该线程休眠一秒
            try {
                Thread.sleep(1000);//单位为毫秒 try-catch快捷键:Ctrl+Alt+T
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (times == 80) {
                break;//当times到80,退出while,这是线程也就退出了
            }
        }
    }
}

3)使用JConsole监控线程执行情况,并画出程序示意图:

如下,在控制台点击run,运行程序,在程序运行时,点击Termial

image-20220903201816455

在控制台输入JConsole,回车。

image-20220903201903908

点击本地进程,点击Thread01,点击下方连接按钮:

image-20220903202032834

在弹出窗口中点击不安全的连接按钮:

image-20220903202109982

在窗口中点击“线程”:

image-20220903202616380

可以在左下角的线程小窗口中看到main线程和Thread-0线程在同时进行

image-20220903202808116

等待一段时间,可以看到当run窗口的主线程 i = 60之后,main线程结束

结束前:

image-20220903203153344

结束后:image-20220903203145376

当线程名称=Thread-0输出到80次时,虽然可以Thread-0还在左下角,但是实际上Thread-0线程已经结束了,整个进程随之结束。

image-20220903204614562

程序示意图:

202209032116

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

2.2为什么是start?

在2.1的例子中,主方法中定义了cat对象,该对象调用了start方法,start方法会去启动一个线程,最终会执行Cat 类的run方法。

思考一个问题:既然最终都是要调用run方法,为什么cat对象还要通过start方法对调用run呢?为什么不直接调用?

答案: 首先通过 对象.run() 方法 可以执行方法,但是不是使用的多线程的方式,就是一个普通的方法,没有真正地启动一个线程。即这时候把run方法执行完毕,才能执行主方法剩下的语句。

如下图:将cat.start();改为cat.run();之后的运行结果:

在run方法执行完之后才执行主方法剩下的语句

image-20220903213334214

那么在调用start方法时,整个过程到底是什么样子的?

点击start()方法:可以在start方法中看到一个start0()方法:

image-20220903213931518

点击start0( )方法:可以看到start0是一个本地方法,由 JVM调用,底层是c/c++实现。

image-20220903214152774

再看看run()方法的源码:可以看到run方法只是简单的调用了实现类的run,没有进行任何的多线程处理。

image-20220903215311977

换而言之,Java中真正实现多线程的效果的是start0方法,而不是run方法

202209032154

标签:01,run,Thread,day31,start,线程,进程,方法
From: https://www.cnblogs.com/liyuelian/p/16653806.html

相关文章

  • 洛谷P1850 [NOIP2016 提高组] 换教室(期望dp)
    #include<bits/stdc++.h>usingnamespacestd;intn,m,v,e;intc[3005],d[3005];intf[305][305];doubledp[3005][3005][2];//dp[i][j][k]表示前i步申请更换了j......
  • 【Oracle初学者】ORA-01034: ORACLE not available
    系统报错代码ORA-01034:ORACLEnotavailable出现原因//在启动实例时,关闭了数据库,导致外部软件无法访问Oracle数据库(大部分都是因为数据库监听或者服务关闭导致出现的......
  • GO语言自学_001_环境配置_windowx11_x64版本
    下载地址:https://golang.google.cn/1、看到那个下载按钮了么?点她!2、点击download到这个页面,根据电脑自身系统配置下载包。3、下载完毕后,运行.msi文件,一路next就可以......
  • Solution Set -「AGC 001~003」C~F
    目录「AGC001C」ShortenDiameter「AGC001D」ArraysandPalindrome*「AGC001E」BBQHard*「AGC001F」WildSwap^「AGC002C」KnotPuzzle「AGC002D」StampRally......
  • 比较:java多线程 sleep()和wait()
    相信看这篇文章的朋友都已经知道进程和线程的区别,也都知道了为什么要使用多线程了。这两个方法主要来源是,sleep用于线程控制,而wait用于线程间的通信,与wait配套的......
  • 2022-2023-1 20221301 《计算机基础与程序设计》第1周学习总结
    2022-2023-120221301《计算机基础与程序设计》第1周学习总结安装Linux操作系统,学习Linux基础这个作业属于哪个课程<班级的链接>(2022-2023-1-计算机基础与程序设计)......
  • vue3项目-小兔鲜儿笔记-分类模块01
    1.二级类目-筛选区展示获取数据进行品牌和属性的渲染<template><divclass="sub-filter"v-if="filterData&&!filterDataLoading"><divclass="item"><......
  • Nginx分布式框架详解61-71静态资源访问-01
    nginx跨域问题的原因分析跨域问题,我们主要从以下方面进行解决:什么情况下会出现跨域问题实例演示跨域问题具体的解决方案是什么同源策略浏览器的同源策略:是一种约定......
  • 2019ACM-ICPC 西安邀请赛 D.Miku and Generals——二分图染色+01背包
    目录题意思路代码目录题意将n个将军卡片分成两份,要求两份卡片之间的差值尽可能小,求最大的那一份卡片的和,这里有m组卡片是不能放在同一份的思路对有矛盾的组我们建图进......
  • P1966 [NOIP2013 提高组] 火柴排队做题笔记
    这题和P5677一样,是从树状数组题单里翻出来的,由于开始看时感觉题解代码写的不是很清晰,就先放进了做题计划里,后来几次看这道题,但由于第一次看题可能留下了一些心理阴影以及......