美文网首页
Java基础-线程 (一)

Java基础-线程 (一)

作者: 森屿暖茶 | 来源:发表于2021-01-29 13:49 被阅读0次

    线程是什么?    

    回答这个问题之前,我们首先需要了解进程。因为线程是在进程中运行的。

    进程:是操作系统调度的最小单元。当一个进程内没有线程时,这个进程就会被销毁。也就是说如果一个进程存活状态,那么它至少拥有>=1个线程。

    线程:是CPU调度(CPU时间片轮转机制)的最小单元,他必须依托于进程。

    拓展: CPU核心数线程数关系。一般情况下是1:1(线程数 = cpu个数 * 核数),现在基本都采用超线程技术达到1:2(线程数 = cpu个数 * 2*核数)

    CPU时间片轮转机制:

    根据先进先出原则,排成队列(就绪队列),调度时,将CPU分配给队首进程,让其执行一个时间段(称为:时间片),时间片通常为10-100ms数量级,当执行的时间片用完时,会由计时器发出时钟中断请求,调度程序便据此来停止该进程的执行,并将它排到队列末尾,然后再把CPU重新分配给当前队列的队首进程,同理如此往复。

    并发和并行

    并行:同一时刻多个任务一起执行的任务,这些任务执行状态就是并行的。(同时的)

    并发:在某一个时间段内,任务的执行量(吞吐量)。因为CPU的时间片轮转机制,可以让CPU在一定时间内交替执行不同任务。 (不是同时的)。并发大大提高了任务的处理效率,但是并发要与实际情况相结合,不能让CPU过累,因为CPU在随机切换的时候也会消耗资源,线程的创建也会消耗资源,一次性创建过多的线程会直接让CPU执行变慢,资源溢出等问题。

    其实我们程序绝大多数情况都是并发多线程执行的。比如当你CPU到达100%的时候,你依旧有机会能够杀死。

    JAVA中线程的调度:主要包含两种:抢占式线程调度器和协作式线程调度器。(所有的Java虚拟机都有一个线程调度器,用来确定哪个时刻运行哪个线程。)

    抢占式线程调度: 每个线程可能会有自己的优先级,但是优先及并不意味着高优先级的线程一定会被调度,而是由CPU随机的选择,所谓抢占式的线程调度,就是说一个线程在执行自己的任务时,虽然任务还没有执行完,但是CPU会迫使它暂停,让其它线程占有CPU的使用权。(线程不能决定自身能够执行完,由CPU决定)(java虚拟机采用抢占式调度模型)

    协作式线程调度: 每个线程可以有自己的优先级,但优先级并不意味着高优先级的线程一定会被最先调度,而是由cpu时机选择的,所谓协作式的线程调度,就是说一个线程在执行自己的任务时,不允许被中途打断,一定等当前线程将任务执行完毕后才会释放对cpu的占有,其它线程才可以抢占该cpu。(线程执行完后,CPU才会调度其他线程)

    Java在调度机制上采用的是抢占式的线程调度机制。

    Java线程在运行的过程中多个线程之间是协作式的。

    线程的启动方式

    本质上2种方式,Thread实现Runnable接口或者自己实现Runnable接口,实际有3种方式:

    无参有2种形式:

    ①内部实现Runnable接口。

    ②实现Runnable接口。

    实现Runnable接口

    带参数返回:本质上是实现Runnable接口

    (Callable、Future和FutureTask)阻塞式返回结果

    常见问题

    Thread .run()和.start()的区别?

    run()是函数调用,Thread实现的Runnable接口。作为普通方法调用,既然是普通方法,那么就是在当前线程顺序执行,并没有一开启一个新线程。(普通方法)

    start(),让线程启动进入准备就绪(准备被执行状态)。等待CPU调度然后执行run方法,这是多线程。(启动线程)

    Thread.join():创建线程,并立马获取到执行权,调用run()执行。

    Thread.sleep():线程挂起进入阻塞状态,挂起一段时间后进入准备就绪状态。sleep可能会抛出InterruptedException异常。

    Thread.wait()、notify()、notifyAll():需在持有锁机制下使用。详见后续。

    Thread.yield():让出当前执行权,一般不会使用到这个方法。

    Thread的各个方法调用的意义和作用。

    我们大致可以用一张图来解释。

    任何暴力的中断线程均会导致线程中资源得不到很好的回收,正确的中断方式是让线程run()执行结束后回收线程。

    线程的中断

    有3种方式:

    ①run方法内内置标志位,让run运行结束

    ②stop,不推荐使用,且已过期。

    ③interrupt()异常法。

    Thread 提供interrupt()方法,内置一个Booean变量记录中断状态。

    interrupt()方法仅仅是在当前线程中打了一个停止的标识将中断标志修改为true,并没有真正的停止线程。如果在此基础上进入堵塞状态(sleep(),wait(),join()),马上就会抛出一个InterruptedException,且中断标志被清除,重新设置为false,线程退出。

    即interrupt()+能够让线程进入堵塞状态的方法(其中有3种方法能够让线程进入堵塞状态:sleep(),wait(),join()),其中join是其他线程调用,抢占线程执行权达到堵塞目的。

    interrupt只是内置的一个boolean变量。我们可以自行定义变量一样可以达到中断的效果。最终实现目的都是让线程run()执行结束。

    相关文章

      网友评论

          本文标题:Java基础-线程 (一)

          本文链接:https://www.haomeiwen.com/subject/mpoggktx.html