java多线程并发编程复习笔记(1)线程基础、Java线程和部分方法的介绍

191 阅读7分钟

一、线程基础

1.什么是进程和线程:

进程:在计算机操作系统中,进程是资源分配的基本单位,也是独立运行的基本单位。

线程:线程是CPU独立调度的基本单位,必须依赖于进程存在。它是进程内的执行单元,比进程小,他的出现是为了见少程序并发执行时所付出的时间、空间的开销。

在操作系统中,多个线程是共享进程的资源的,及多个线程驻留在相同的地址空间中,共享数据和文件。但在JMM(java内存模型)里,每个线程有自己的内存空间,每个线程不能修改其它线程和内存里的数据,只能修改自己空间里的数据(运行前拷贝到线程自己的工作内存)。

2.核心数和线程的关系

核心:cpu,处理器。在引入超线程技术之前,一个核心只能执行一个线程,多核心是为了并行的处理程序,提高计算机的计算能力。(在intel引入超线程技术之后,一核心可以并行执行两个线程)

图片1.png

3.时间片轮转机制

百度百科对CPU时间片轮转机制原理解释如下:

如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结来,则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾

口头上理解:在微观的角度上,多个进程(或线程),在一个CPU的条件下,CPU在一个时间片的时间里给一个线程进行计算,在下一个时间片给另外的一个线程进行计算。(具体给哪个线程或进程用根据操作系统的调度算法来分配的。可以看一下操作系统的书进行深度了解)

4.并发和并行

并行:同时执行,在某个时间片时间里(很短的时间),可以执行的多个线程。(上图理论上最多了并行处理8个线程)

并发:基于时间片轮转机制。在单个CPU的情况下,计算机在人的感觉上依然可以运行多个线程,其实是多个线程在交替的使用CPU。(人的感觉是因为计算机执行速度太快)

图片2.png

二、JAVA里的线程

1.java里的程序天生就是多线程的,线程有几种启动方式。

  1. 类Thread
  2. 接口Runnable

微信图片_20210530094811.png

微信图片_20210530094830.png

根据Thread类上的注释可见,线程创建的方式有两种,一种是基于Thread,另一种是基于Runable接口。

Thread和Runnable的区别:

  Thread才是Java里对线程的唯一抽象,Runnable只是对任务(业务逻辑)的抽象。Thread可以接受任意一个Runnable的实例并执行。
  

2.线程的状态。

线程总共有6种状态:

1.NEW:尚未启动的线程的线程状态,刚创建出来

2.RUNNABLE:包括操作系统中的Running和Ready状态,Running是运行中,Ready是等待CPU资源(次是其它资源已经准备完毕)。

3.WAITING:等待状态,除了synchronized线程锁的竞争出现的停止状态外,包括wait(),join(),Lock.park()等方法的掉用都会进入这个状态。

4.BLOCKED:当多线程在竞争相同对象(或对象实例)Synchronized()的时候,才会出现这个状态。

5.TIMED_WAITING:具有指定等待时间的等待线程的线程状态,及掉用可以线程具体等待时间的方法。例如:join(long)

6.TERMINATED:终止线程的线程状态,线程已经完成了执行。

20181120173640764.jpeg

3.线程的停止方式

1.不推荐(过期)的方式:suspend()暂停、stop()停止。

  • suspend:在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。
  • stop:在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。 2.推荐方式:interrupt()中断方式。
  • 通过interrupted()和isInterrupted()来进行退出的判断。

微信图片_20210530104443.png

  • 通过状态标识和阻塞来退出

微信图片_20210530103803.png

java中线程是协作的关系而不应该是强制的关系,及去通知线程暂停和关闭。等线程安全处理完当前的操作后再进行相应的暂停和关闭操作。

4.interrupt()、interrupted()、isInterrupted()的区别。

interrput():掉用该方法的线程会背标记成阻塞的状态。阻塞状态的判断是通过interrupted()、isInterrupted()来进行判断的。

interrupted():这是个静态的方法,通过Thread来掉用,掉用次方法会返回当前的中断状态。如果返回的是true,则表示线程调用过interrput()方法,并且会重置当前阻塞状态为false。

isInterrupted():掉用此方法会判断当前中断的状态,如果掉用过interrput()则返回true,否则是false.

interrupted()和isInterrupted()的区别在于interrupted()会重置中断状态,isInterrupted()不会。

5.简单介绍yield(),Join()方法

yield():执行该方法的线程会放弃CPU的占有权。所有执行yield()的线程有可能在进入到就绪状态后会被操作系统再次选中马上又被执行。

Join():执行该方法的线程,会执行完线程该线程后再继续后续代码的执行。举例:在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

6.wait(),notify(),notifyAll()方法是要跟synchronized一起使用。

这三个方法是每个Object.class里的方法,都是对上锁的对象进行掉用及synchronized(Object){},Object为上锁的对象。

wait():调用该方法的线程进入WAITING状态,只有等待另外线程的通知或被中断才会返回.需要注意,调用wait()方法后,会释放对象的锁。

notify():通知一个在对象上等待的线程,使其从wait方法返回,而返回的前提是该线程获取到了对象的锁,没有获得锁的线程重新进入WAITING状态。当多个线程在WAITING状态下,掉用此方法不知道具体会唤醒哪个线程。

notifyAll():通知所有WAITING在该对象上的线程。

在调用wait()、notify()系列方法之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法、notify()系列方法,进入wait()方法后,当前线程释放锁,在从wait()返回前,线程与其他线程竞争重新获得锁,执行notify()系列方法的线程退出调用了notifyAll的synchronized代码块的时候后,他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出synchronized代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

三、注意和补充

1.操作系统里,CPU时间片的分配是根据进程进心分配的。但java里的线程都是内核级别的线程,所以平时现在学习java多线程相关的内容的时候才会忽略进程,直接把CPU跟线程进绑在一起。 2.很多细节如果要扣的很清楚需要根据《操作系统》这本书的知识才能从底层搞明白为什么去那样涉及。有精力的小伙伴可以去好好看看,以笔者的经验,不同阶段看这本书的感受都会不同,笔者现在都有想法再去看一下这本书了。