网站首页 > java教程 正文
- 线程的生命周期及五种基本状态
- JAVA线程具有五种基本状态
新建状态(new):使用new关键字实例化一个线程对象并未调用start()阶段,该阶段在堆内存中为该对象分配内存空间并且无法参与抢夺CPU的使用权。
就绪状态(Runnable):一个线程对象调用start()方法后,直到运行完run()方法的这个阶段,线程一旦就进入就绪阶段,java虚拟机为该线程创建方法的调用栈和计数器等。
备注:但凡处于就绪状态的线程都被视为活动状态,可以使用isAlive()方法查看线程是否处于就绪状态,使用activeCount()查询当前线程所在线程池的活动线程数,处于就绪状态的线程并不是运行状态(有参与抢夺CPU的使用权限)。
运行状态(Running):当CPU开始调度处于就绪状态的线程并执行线程的run()方法,此时线程才得以真正执行,即进入到运行状态。
备注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中。
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。
根据阻塞产生的原因不同,阻塞状态又可以分为三种:
等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
同步阻塞 -- 线程获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
- Java多线程的阻塞状态与线程控制
join():当前线程调用某个线程的join()时,使当前线程陷入等待状态,等待某个线程执行完成后当前线程才能继续执行。join实现线程等待是其内部调用线程wait()方法,使其当前线程处于等待状态。
join-demo
package com.thread.demo2;
public class Main {
public static void main(String[] args) {
JoinCounter joinCounter = new JoinCounter();
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
joinCounter.printA();
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
joinCounter.printB();
}
});
Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
joinCounter.printC();
}
});
threadA.start();
try {
/**
* 当前线程(主线程)调用A线程的join()时,使当前线程(主线程)陷入等待状态,A线程执行完成后当前线程才能继续执行,join实现线程等待是其内部调用线程wait()方法,使其当前线程处于等待状态。
*/
threadA.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
threadB.start();
threadC.start();
}
static class JoinCounter {
public void printA() {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-------A---------");
}
public void printB() {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("------------B-------------");
}
public void printC() {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("------------C-------------");
}
}
}
执行结果:
sleep():让当前的正在执行的线程暂停指定的时间,并进入阻塞状态。在其睡眠的时间段内,该线程由于不是处于就绪状态,因此不会得到执行的机会。即使此时系统中没有任何其他可执行的线程,出于sleep()中的线程也不会执行。因此sleep()方法常用来暂停线程执行。暂时放弃cpu的执行权, 但不会释放锁。
sleep-demo
package com.thread.demo2;
public class SleepThreadMain {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("-----------run()---------调用sleep方法,线程暂停指定的时间,进入阻塞状态" );
Thread.sleep(1000);
System.out.println("-----------run()---------sleep方法睡眠超时,被唤醒,进入执行状态");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
}
}
执行结果:
yield():yield()方法还与线程优先级有关,当某个线程调用yiled()方法从运行状态转换到就绪状态后,CPU从就绪状态线程队列中只会选择与该线程优先级相同或优先级更高的线程去执行。
yield-demo
package com.thread.demo2;
public class YieldThreadMain {
public static void main(String[] args) {
//创建两个线程
Thread t1 = new YieldThread("线程A");
Thread t2 = new YieldThread("线程B");
//开启两个线程
t1.start();
t2.start();
}
//线程让步
//定义 YieldThread 类继承 Thread 类
static class YieldThread extends Thread {
//定义一个有参的构造方法
public YieldThread(String name) {
super(name); //调用父类的构造方法
}
public void run() {
System.out.println(Thread.currentThread().getName() + " ---------run()执行业务---------");
System.out.println("线程让步:");
Thread.yield(); //线程运行到此,作出让步
System.out.println(Thread.currentThread().getName() + " ---------run()执行完成---------");
}
}
}
执行结果:
改变线程的优先级/setPriority():每个线程在执行时都具有一定的优先级,优先级高的线程具有较多的执行机会。每个线程默认的优先级都与创建它的线程的优先级相同。main线程默认具有普通优先级。设置线程优先级:setPriority(int priorityLevel)。参数priorityLevel范围在1-10之间,常用的有如下三个静态常量值:
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
获取线程优先级:getPriority()
注:具有较高线程优先级的线程对象仅表示此线程具有较多的执行机会,而非优先执行
notify()和notifyAll()唤醒线程:
notify():只能唤醒等待(调用wait()方法等待)同一个对象的随机一个线程获得到锁,其他没有得到锁的线程会继续保持在等待状态。
notifyAll():只能唤醒等待(调用wait()方法等待)同一个对象的所有线程,notifyAll()方法执行后,只有一个线程能得到锁,其他没有得到锁的线程会继续保持在等待状态。
notify-demo
执行结果:
猜你喜欢
- 2025-03-19 面试官:使用int类型做加减操作,是线程安全吗
- 2025-03-19 Redis多线程版本是如何保证线程安全的?
- 2025-03-19 JAVA多线程编程-线程安全性AtomicInteger原子操作
- 2025-03-19 C# 并发请求中的线程安全问题(c#多线程编程实战与c#并发编程经典实例)
- 2025-03-19 为什么i++用volatile是存在线程安全问题的?
- 2025-03-19 并发编程三要素是什么?在 Java 程序中怎么保证多线程的运行安全?
- 2025-03-19 为什么?为什么StringBuilder是线程不安全的?
- 2025-03-19 面试突击18:为什么ConcurrentHashMap是线程安全的?
- 2025-03-19 为什么 HashMap 是线程不安全的(为什么hashmap是线程不安全的)
- 2025-03-19 介绍一下Python中的线程安全和如何实现
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)