Java concurrent program - Java 线程初探

1.创建和运行线程

方法一,直接用Thread
在这里插入图片描述
例如:
在这里插入图片描述
方法二,使用Runnable配合Thread。Thread 代表线程,Runnable 可运行的任务(线程要执行的代码)。
在这里插入图片描述
例如:
在这里插入图片描述
用lambda精简代码
在这里插入图片描述
方法三,FutureTask 配合 Thread
在这里插入图片描述

2.多个线程同时运行

  • 交替执行
  • 谁先谁后,不由我们控制

3.查看进程线程的方法

windows

  • 任务管理器可以查看进程和线程数,也可以用来杀死进程
  • tasklist查看进程
  • taskkill杀死进程

Linux

  • ps -fe查看所有进程
  • ps -fT -p查看某个进程(PID)的所有线程
  • kill杀死进程
  • top按大写H切换是否显示线程
  • top -H -p查看某个进程(PID)的所有线程

Java

  • jps命令查看所有Java进程
  • jstack查看某Java进程(PID)的所有线程状态
  • jconsole来查看某个Java进程中线程的运行情况(图形界面)

4.线程运行的原理

栈与栈帧

每个线程启动后,虚拟机就会为其分配一块栈内存。每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存。每个线程只能有一个活动栈帧(位于栈顶),对应着当前正在执行的那个方法。

线程上下文切换

CPU不再执行当前的线程,转而执行另外一个线程称为线程上下文切换。频繁发生线程上下文切换会影响性能。有以下原因导致线程上下文切换。

  • 线程的CPU时间片用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
    当发生线程上下文切换时,JVM通过程序计数器来保存当前线程的状态,并且记住下一条JVM指令的执行地址,是线程私有的。

5.常见方法

在这里插入图片描述
在这里插入图片描述

6.start与run

  • 直接调用run是在主线程中执行了run,没有启动新的线程
  • 使用start是启动新的线程,通过新的线程间接执行run中的代码

7.sleep 与 yield

Sleep

  • 调用sleep会让当前线程从Running进入Timed Waiting状态(阻塞)。
  • 其它线程可以使用interrupt方法打断正在睡眠的线程,这时sleep方法会抛出 InterruptedException。
  • 睡眠结束后的线程未必会立刻得到执行。

Yield

  • 调用yield会让当前线程从Running进入Runnable就绪状态,然后调度执行其它线程。
  • 具体的实现依赖于操作系统的任务调度器。

线程优先级

  • 线程优先级会提示调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它。
  • 如果CPU比较忙,那么优先级高的线程会获得更多的时间片,但CPU空闲时,优先级几乎没作用。
  • 可以通过setPriority方法来为线程设置优先级。最小优先级是1,最大是10。默认优先级是5。

8.join

join用来等待调用join方法的线程执行结束。用于线程同步。
join(long time)有时间限制的等待,如果时间到了没有执行完也直接结束,如果提前执行完了就提前结束等待。

9.interrupt

Interrupt方法用于打断阻塞线程(wait、sleep、join),join的底层原理就是wait。打断阻塞线程会清空打断状态。比如打断sleep时,isInterrupted方法会显示false。
打断正常运行的线程不会清空打断状态。isInterrupted方法会显示true。
打断park线程, 不会清空打断状态。果打断标记已经是true, 则park会失效。可以使用 Thread.interrupted()清除打断状态,这样可以重新调用park()。

10.主线程和守护线程

默认情况下,Java进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。
垃圾回收器线程就是一种守护线程。

11.五种状态

在这里插入图片描述
初始状态:仅是在语言层面创建了线程对象,还未与操作系统线程关联。
可运行状态(就绪状态):指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行。
运行状态:指获取了 CPU 时间片运行中的状态。当CPU时间片用完,会从运行状态转换至可运行状态,会导致线程的上下文切换。
阻塞状态:如果调用了阻塞 API,如 BIO 读写文件,这时该线程实际不会用到 CPU,会导致线程上下文切换,进入阻塞状态。等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换至可运行状态。与可运行状态的区别是,对阻塞状态的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们。
终止状态:表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值