线程五大状态
- 创建状态
- 就绪状态
- 阻塞状态
- 运行状态
- 死亡状态
状态结构导图
线程方法
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程体休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程(此方法尽量少用) |
boolean isAlive() | 测试线程是否处于活动状态 |
线程停止
建议:
- 建议线程正常停止,即利用次数,不建议死循环。
- 建议使用标志位,即设置一个标志位。
- 不建议使用stop或者destroy等过时以及JDK不建议使用的方法。
代码
//线程停止
public class Thread05 implements Runnable{
//设置标志位
private boolean flag = true;
//线程运行
@Override
public void run() {
int count = 0;
while (flag){
System.out.println("Run......" + count++);
}
}
//创建一个class,改变标志位
public void ThreadStop(){
this.flag = false;
}
public static void main(String[] args) {
//开启线程
Thread05 thread05 = new Thread05();
new Thread(thread05).start();
//制约线程停止的条件
for (int i = 0; i < 100; i++) {
System.out.println("main......" + i);
if (i == 50){
thread05.ThreadStop();
System.out.println("线程停止");
}
}
}
}
注意:这里只是run()方法的线程停止,而主线程并未停止,而是一直运行到循环结束。
图示
线程休眠
sleep作用:
- sleep(时间)指定当前线程阻塞的毫秒数。
- sleep存在异常interruptedException。
- sleep时间到达后线程进入就绪状态。
- sleep可以模拟网络延时,倒计时等。
- 每一个对象都有一个锁,sleep不会释放锁。(后面回过头在来理解。)
模拟网络延时
代码
模拟抢票
public class Thread06 implements Runnable{
private int piao = 1;
@Override
public void run() {
while (true){
if (piao > 10){
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "拿到了第" + piao++ + "张票");
}
}
public static void main(String[] args) {
Thread06 thread06 = new Thread06();
new Thread(thread06,"小明").start();
new Thread(thread06,"小红").start();
new Thread(thread06,"黄牛党").start();
}
}
图示
注意:模拟延时会放大问题的发生性
模拟倒计时
代码
public class Thread07 implements Runnable{
@Override
public void run() {
int math = 10;
while (true){
if (math <= 0){
break;
}
System.out.println(math--);
//模拟倒计时,1000为一秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread07 thread07 = new Thread07();
new Thread(thread07).start();
}
}
拓展(获取系统当前时间)
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;
//获取当前时间
public class Thread070 implements Runnable{
@Override
public void run() {
//打印当前系统时间
Date starTime = new Date(System.currentTimeMillis()); //获取当前时间
while (true){
try {
System.out.println(new SimpleDateFormat("HH:mm:ss").format(starTime));
Thread.sleep(1000);
starTime = new Date(System.currentTimeMillis()); //更新当前时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread070 thread070 = new Thread070();
new Thread(thread070).start();
}
}
线程礼让
礼让yield:
- 礼让线程,让当前正在执行的线程暂停,但不阻塞。
- 讲线程从运行状态转为就绪状态。
- 让CPU重新调度,礼让不一定成功!看CPU的心情。(完全看CPU的心情)
代码
public class Thread08 {
public static void main(String[] args) {
Yield yield = new Yield();
new Thread(yield,"小明").start();
new Thread(yield,"小红").start();
}
}
class Yield implements Runnable{
@Override
public void run() {
System.out.println("我想对很礼貌" + Thread.currentThread().getName());
Thread.yield(); //线程礼让
System.out.println("最后我又不想和你交流" + Thread.currentThread().getName());
}
}
图示
注意:即使不加Thread.yield();也会礼让,只是添加后会使得礼让更加的频繁。
强制执行
强制Join:
- Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。
- 相当于排队打饭中的插队。
代码
public class Thread09 {
public static void main(String[] args) throws InterruptedException {
Join join = new Join();
Thread thread = new Thread(join);
thread.start();
for (int i = 1; i <= 2000; i++) {
if (i == 200){
thread.join();
}
System.out.println("普通用户" + i + "在排队");
}
}
}
class Join implements Runnable{
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
if (i % 2 == 0){
//此处为防止子线程运行过快在200号之前就跑完的情况
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("VIP用户" + i + "在排队");
}
}
}
图示
图二的原因解释:强制执行并不是阻止子线程在200号打饭之前停止运行,而是假如20位VIP客户没有在200号之前排完队打饭,这时候VIP的作用显示出来,让剩余的VIP客户直接排在199号,直到VIP客户排完打饭后,普通用户在接着200号排队打饭
守护线程
守护概述:
- 线程分为用户线程和守护线程。
- 虚拟机必须确保用户线程执行完毕。
- 虚拟机不用等待守护线程执行完毕。
- 如,后台记录操作日志,监控内存,垃圾回收。
thread.thread.setDaemon(),一般情况下默认为false,表示为用户线程,正常的线程都是用户线程。
代码
public class Thread12 {
public static void main(String[] args) {
God god = new God();
Youself you = new Youself();
Thread thread = new Thread(god);
thread.setDaemon(true);
thread.start();//开始上帝保佑
new Thread(you).start();//开启你的人生之路
}
}
//上帝默默保佑着你
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("God is watching over you");
}
}
}
//你还在世上
class Youself implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你还活着");
}
System.out.println("======The end of life======");
}
}
图示
观测线程状态
-
Thread.State()
-
NEW
尚未启动的线程处于此状态。
-
RUNNABLE
在Java虚拟机中执行的线程处于此状态。
-
BLOCKED
被阻塞等待监视器锁定的线程属于此状态。
-
WATTING
正在等待另一个线程执行特定动作的线程处于此状态。
-
TIMED_WATTING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
-
TERMINATED
已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态 。这些状态是不反映任何操作系统线程状态的虚拟机状态。
代码
public class State { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(()->{ //lamda表达式 for (int i = 0; i < 10; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Run......"); } }); //观测状态 Thread.State state = thread.getState(); //NEW System.out.println(state); //启动后 thread.start(); state = thread.getState(); System.out.println(state); //Run while (state != Thread.State.TERMINATED) { Thread.sleep(100); state = thread.getState(); System.out.println(state); //阻塞sleep,TIMED_WAITING } } }
图示
-
线程运行结束后便死亡,不能重复开始线程
评论区