Java EE——Thread方法和线程不安全原因

Thread方法

构造函数

方法名说明
Thread(String name)构建线程时可以给线程起名
Thread(Runnable runnable String name)传入runnable实例并取名

其他方法

先列一个表,后面一一介绍

方法获取属性
getId()ID(身份标识)
getName()名称
getState()状态
getPriority()优先级
isDaemon()是否时后台线程
isAlive()是否存活
isInterrupted()是否被中断

ID

我们的线程有许多的ID,此处的ID指的是JVM中为线程指定的ID,此外还有操作系统线程API中的ID,还有PCB中的ID

名称

就是我们刚才讲的,在创建线程时为线程起的名字

优先级

就是线程执行的优先程度

后台线程

如果线程是前台线程,那么main函数执行完,进程会等线程运行结束后再退出(main也是前台进程),我们对一些不重要的数据(可以模棱两可的)可以使用后台进程,以减少系统资源的消耗,例如记录步数

是否存活

Thread类对象和真实的系统内核虽然是一一对应的关系,但是并不是同生共死的,当我们的Thread类创建出来时,内核线程并没有创建,而是等Thread调用start方法才创建线程,而当run执行完成后,内核线程就销毁了,但是Thread对象还有,因此我们调用isAlive()判断线程的真实状态

start和run区别

直接调用run方法并不会创建线程,而是单纯的运行其内部的代码,而调用start才会创建线程,然后和其他的线程并发执行

中断

一般来说,我们的线程会等run执行完后才会结束,我们可以通过下面这个办法来提前中断线程

thread.interrupt();

我们的isInterrupt()方法就是判断这个interrupt背后的标识位是否为true

然而设置interrupt也有例外,当我们的线程正在sleep状态,那么不会设置标志位为true,而是触发异常(InterruptedException),该异常会让sleep的线程提前唤醒

join

当我们调用t.join()时,我们的main就会阻塞等待,直到t线程执行完毕,而如果在调用join时,t线程已经执行完毕,那么就不用阻塞等待了

join()还可以传参数,其参数是时间,当我们等到这个时间到了的时候,线程就不再阻塞等待了

sleep

调用这个方法时,线程的PCB就不在链表中了,而是进入一个阻塞队列,直到到了时间再回到链表中

当然,并不是一唤醒就可以直接到CPU上执行工作,而是看调度的时间开销。也有一些操作系统通过一些计算是可以做到实时调用的,例如发火箭就需要这个系统

状态

以下的状态是Java对于线程状态的描述,并不是PCB中的状态

  1. NEW Thread对象创建完毕,但是PCB没有创建
  2. TERMINATED PCB被销毁,Thread对象还未销毁
  3. RUNNABLE 正在运行或者在就绪队列中
  4. TIMED_WAITED 调用sleep,join,阻塞中
  5. WAITING 调用wait,另一种阻塞,之后讲
  6. BLOCKED 等待锁时的阻塞,之后讲

线程安全

当我们让两个线程同时对一个数据进行多次自增操作时,可能会出现线程不安全的情况,这个情况就是最终加出来的数是随机的,每一次运行的结果都有可能不一样

这个结果出现的原因就是我们的自增操作并不是原子性的,即他是分成三条语句执行的,先将数据从内存读到CPU,再在寄存器中加一,然后再写回到内存中,而当我们双线程进行多次自增时,可能会出现类似于MySQL中的脏读问题

例如,我们理想情况下,count是1,A线程先读是1,然后自增,然后A放回,count变为2,B线程读count是2,B再放回是3.

但有可能出现下面的情况

A线程先读是1,然后自增,这个时候B线程也读count是1,然后A放回,count变为2,B再放回还是2.

至于如何解决这种问题,我们稍后的blog会进行讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值