Java多线程的实现(进程与线程的概念、继承Thread类实现多线程、实现Runnable接口实现多线程、继承Thread类与实现Runnable接口的区别、实现Callable接口实现多线程)

1 进程与线程

1.1 进程与线程的概念

  Java是第一门原生支持多线程的高级语言
什么是进程?
  进程: 在一个操作系统中,每个独立执行的程序都可称之为一个进程,也就是“正在运行的程序”。Windows操作系统下,鼠标右键单击任务栏,选择【启动任务管理器】选项可以打开任务管理器面板,在窗口的【进程】选项卡中可以看到当前正在运行的程序,也就是系统所有的进程。

在这里插入图片描述
  多进程: 同一时刻跑多个(进程)程序。比如我们在用腾讯视频看电视的时候照样可以登录qq和朋友聊天
  在DOS(磁盘操作系统时代),由于其本身就是一个单进程的操作系统,所以在同一时间段上只能够有一个程序执行;后来发展到Windows系统后,我们可以发现多个程序可以同时执行,所以Window是一个多进程的操作系统。现在基本上所有的操作系统都是多进程。
什么是多线程?
  一个程序(进程)可以执行多个任务,通常,每一个任务就称之为一个线程。登录qq和朋友聊天,此时肯定存在读线程和写线程同时运行。

1.2 对比进程、线程

  • 与进程相比,线程更加的轻量级,创建、撤销一个线程比启动、撤销一个进程开销要小的多,并且一个进程中的所有线程共享此程序(进程)的所有资源。
  • 没有进程就没有线程,进程一旦终止,其内的线程也将不复存在。就像你登录QQ和朋友聊天,如果某一时刻你关掉了QQ,读线程和写线程也将不复存在
  • 进程是操作系统资源调度的基本单位,进程可以独享资源;线程需要依托进程提供的资源,无法独立申请操作系统资源,是操作系统任务执行的基本单位。
    多进程与多线程的区别?
      本质区别在于,每个进程拥有自己的一整套变量,而线程则共享数据,共享变量使得线程之间的通信比进程之间的通信更加有效方便。

1.3 高并发

  高并发指的是:同一时刻线程的访问量非常高
  高并发带来的问题:服务器内存不够用,无法处理新的请求
在这里插入图片描述

1.4 线程的状态

在这里插入图片描述

2 Java的多线程实现

2.1 继承Thread类实现多线程

  java.lang.Thread是一个线程操作的核心类,(java.lang包会自动导入,所以不需要手动书写)新建一个线程最简单的方式就是直接继承Thread类,而后覆写该类中的run()方法。(就相当于主线程的main方法,每个线程都应该有一个入口,主方法是主线程的入口,run方法是线程入口
继承Thread定义线程

class MyThread extends Thread{
   
    private String title;
    public myThread(String title) {
   
        this.title = title;
    }
    @Override
    public void run()  //所有线程从此处开始运行
    {
   
        for(int i=0;i<10;i++)
        {
   
            System.out.println(this.title+" i="+i);
        }
    }
}

  新建一个线程最简单的方式就是继承Thread类,而后覆写该类中的run()方法,很自然我们就想到产生线程类的实例化对象而后调用run()方法。
在这里插入图片描述
  显然,这个时候只做了顺序打印,和多线程一点关系都没有(多线程的意思是任务同时进行所有不可能顺序打印)可见启动多线程的方式错误。
启动多线程public synchronized void start() 此方法会自动调用线程的run()方法
在这里插入图片描述
  无论哪种方式实现多线程,线程启动一定调用Thread类的start()方法,而不是直接对象名.run()
看start()的源码:
在这里插入图片描述

  1. 首先我们看到在start()方法中抛出IllegalThreadStateException线程状态异常,按照原有处理方式,应当在调用处进行异常处理,然而此处没有处理也不会报错,因此是一个RunTimeException(非受查异常),这个异常的产生只是因为你重复启动了线程才会产生,所以每一个线程对象只能够启动一次
    在这里插入图片描述
  2. 我们看到在start()方法中调用了start0()方法,而这个方法是一个只声明而未实现的方法,同时使用native关键字进行定义。private native void start0();
    native指的是调用本机的原生系统函数:(方法体在C语言中实现)
    Thread类有个 registerNatives 本地方法,该方法主要的作用就是注册一些本地方法供 Thread 类使用,如 start0(),stop0() 等等,可以说,所有操作本地线程的本地方法都是由它注册的。
    这个方法放在一个 static 语句块中,当该类被加载到 JVM 中的时候,它就会被调用,进而注册相应的本地方法。而本地方法 registerNatives 是定义在 Thread.c 文件中的。
    在这里插入图片描述
    Thread.c 是个很小的文件,它定义了各个操作系统平台都要用到的关于线程的公用数据和操作,如下:
    在这里插入图片描述
      观察上边一小段代码,可以容易的看出 Java 线程调用 start->start0 的方法,实际上会调用到 JVM_StartThread 方法,那这个方法又是怎么处理的呢?
    在这里插入图片描述
      综上可知,Java线程创建的调用流程为::调用Thread类的start()(Java方法)方法,判断线程是不是新创建的,如果不是新创建的抛出IllegalThreadStateExcepti
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值