线程基础、线程之间的共享和协作
1、什么是进程和线程
进程是操作系统资源分配的最小单位、其中包括:cpu、内存、磁盘IO等,同一进程中的多条线程共享该进程中的全部系统资源, 线程是cup调度的最小单位,线程是依赖于进程的不能独立存在
2、cup核心数和线程数的关系
例如:
看上图所示当前机器cpu 配置为4核4线程 核心数和线程数的关系为1:1 在引入超线程技术后核心数和线程数的关系为1:2
注:linux内核限制一个进程最多开启1000个线程 windows最多新建2000个线程
3、cpu时间片轮转机制
cup时间片轮转又称RR调度是一种最古老、最简单、最公平的算法,每个进程被分配一个时间段,称作cup的时间片(该进程允许运行的时间)
cup时间片轮转机制会引起上下文切换,上下文切换需要保存之前未完成的信息到寄存器,将要运行的进程信息载入寄存器这个过程需要消耗大量的时间
如果时间片设置太长,用户并发数量上来后需要等待的时间变长,如果时间太短会导致频繁的发生上下文切换,大量的时间都消耗进程或者线程的切换上,现在操作系统cup
基本设置的时间段为:100ms
4、多线程程序注意事项
(1)线程安全
线程是共享进程资源比如内存,cup等,当多个线程同时写共享变量是会引起线程安全问题,要考虑线程同步
(2)线程死锁
为了解决线程安全问题引入了java锁机制,但是当多个线程获取一个被占用了对象锁,如果这个锁一直不释放那么其他线程将会一直等待进而引起死锁
(3)线程数太多引起服务宕机
系统创建大量的线程会消耗很大的内存和cup资源,以及频繁的上下文切换,所有在开发过程中尽量使用线程池防止频繁的创建大量的线程。
5、线程的启动和停止
(1)创建线程有两种方式
第一种:类继承Thread 第二种:实现Runnable接口 通过start 方法启动一个线程
(2)Thread和 Runnable 的区别
Thread 是对线程的抽象,Runnable 是对任务的抽象
(3)线程中止
run方法运行完、抛出一个未处理的异常
(4)stop 、suspend、resume
stop是停止线程 、suspend 暂停线程、resume 恢复线程 这些方法都已经是废弃的方法,jdk中不建议使用
suspend 调用后不会释放已经占有的资源、而是占着资源进入休眠状态容易引起死锁、stop终止一个线程不能保证当前线程资源正常释放
正是因为这些方法有副作用,所有jdk中不再建议使用。
(5)interrupt、interrupted isInterrupted
interrupt 是中断线程,是将中断标志位设置为true,不代表线程会立刻停止工作
interrupted 检测当前线程是否中断,会重置线程状态为false,是静态方法
isInterrupted 是检查当前线程是否中断,不会重置线程状态
注:处于死锁状态的线程是无法被中断的
(6) yield
yield() 方法:是当前cup让出占有权,让出的时间是不可设定的,但是不会释放锁资源,我们在使用yield()
方法是可以在释放锁资源后再调用yield 方法,在调用yield方法进入就绪状态后,有可能再次进入运行状态
(7) join
把指定的线程插入到当前线程中进行执行,比如有两个线程A和B,在运行A线程的时候在A线程中执行B.join() 方法,
此时就会执行B线程,等到B线程运行结束后再继续执行A线程(可以设置线程顺序执行)