线程是进程内部的一个执行单元,它是程序中一个单一的顺序控制流程;如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为 多线程
线程的创建01
1:继承Thread类
2:重写run方法(线程执行体)
3:创建继承了Thread类的对象;调start()方法启动
线程的创建02
1:实现 Runnable接口
2:重写run方法(线程执行体)
3:创建Runnable接口的实现类对象
4:创建一个Thread线程;然后把创建好的实现类对象丢入Thread中;然后调start()方法启动
两种线程创建方式的比较
继承Thread类方式的多线程:
- 优势:编写简单
- 劣势:无法继承其它父类
实现Runnable接口方式的多线程:
- 优势:可以继承其它类,多线程可共享同一个Runnable对象
- 劣势:编程方式稍微复杂,如果需要访问当前线程,需要调用Thread.currentThread()方法
线程启动的注意事项
- 新建的线程不启动不执行,必须通过start()方法调用
- 不能直接调用run()来启动线程,这样run()将作为一个普通方法立即执行
- Java程序启动时,会立刻创建主线程,main就是在这个线程上运行;当不再产生新线程时, 程序就是单线程
线程的生命周期
新生状态:
- 用new关键字建立一个线程对象后,该线程对象就处于新生状态
- 处于新生状态的线程有自己的内存空间,通过调用start进入就绪状态
就绪状态:
-
处于就绪状态线程具备了运行条件,但还没分配到CPU,处于线程就绪队列,等待系统为其分配CPU
-
当系统选定一个等待执行的线程后,它就会从就绪状态进入执行状态,该动作称之为“cpu调度”
运行状态:
- 在运行状态的线程执行自己的run方法中代码,直到等待某资源而阻塞或完成任务而死亡
- 如果在给定的时间片内没有执行结束,就会被系统给换下来回到等待执行状态
阻塞状态:
- 处于运行状态的线程在某些情况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入阻塞状态
- 在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行
死亡状态:
- 死亡状态是线程生命周期中的最后一个阶段。线程死亡的原因有三个:一个是正常运行的线程完成了它的全部工作;另一个是线程被强制性地终止,如通过执行stop方法来终止一个线程【不推荐使用】;三是线程抛出未捕获的异常
优先级
1:Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器
按照线程的优先级决定应调度哪个线程来执行。
2: 线程的优先级用数字表示,范围从1到10
• Thread.MIN_PRIORITY = 1
• Thread.MAX_PRIORITY = 10
• Thread.NORM_PRIORITY = 5 (默认为5)
3: 使用下述方法获得或设置线程对象的优先级。
• int getPriority();
• void setPriority(int newPriority);
4:注意:优先级低只是意味着获得调度的概率低。并不是绝对先调用优先级高后调用
优先级低的线程
线程控制方法
join ()
• 阻塞指定线程等到另一个线程完成以后再继续执行;也可以理解为插队线程
sleep ()
• 使线程停止运行一段时间,将处于阻塞状态;也可以理解为线程的休眠
• 如果调用了sleep方法之后,没有其他等待执行的线程,这个时候当前线程不会马上恢复执行!
yield ()
• 让当前正在执行线程暂停,不是阻塞线程,而是将线程转入就绪状态;也可以理解为线程的礼让,就是礼让 让其他线程优先执行,但是礼让不一定成功
• 如果调用了yield方法之后,没有其他等待执行的线程,这个时候当前线程就会马上恢复执行!
setDaemon ()
• 可以将指定的线程设置成守护线程
• 创建守护线程的线程结束时,守护线程也随之消亡
• 只能在线程启动之前把它设为守护线程