Java多线程:线程状态
线程状态
- 创建状态
- 就绪状态
- 运行状态
- 阻塞状态
- 死亡状态,一旦结束无法再启动
线程方法
线程停止
- 不推荐使用JDK提供的
stop()
,destory()
方法停止线程,推荐线程自己停止下来 - 建议使用一个标志位进行中止变量,当
flag = false
,中止线程运行 - 建议线程正常停止,利用次数,不进行死循环
public class TestStop implements Runnable{
//设置标志位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag){
System.out.println("run" + i++);
}
}
//设置公开方法停止线程,转换标志位
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 200; i++) {
System.out.println("main" + i);//计时
if (i == 99){
testStop.stop();
System.out.println("stop");
break;
}
}
}
}
线程休眠sleep
sleep(时长)
:指定当前线程阻塞的毫秒数- sleep存在异常
InterruptedException
- sleep时间达到后线程进入就绪状态
- sleep可以模拟网络延时,倒计时等(放大问题的发生性)
- 每一个对象都有一个锁,sleep不会释放锁
倒计时
public static void tenDown() throws InterruptedException {
int num = 10;
while (true){
System.out.println(num--);
Thread.sleep(1000);
if (num < 0){
break;
}
}
}
显示当前时间
public static void main(String[] args) {
//打印当前时间
Date startTime = new Date(System.currentTimeMillis());
while(true){
try {
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
Thread.sleep(1000);
startTime = new Date(System.currentTimeMillis());//刷新时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
线程礼让yield
- 让当前正在执行的线程暂停,但不阻塞
- 令线程从运行状态转变为就绪状态
- 令CPU重新调度,但不一定成功
public class TestYield {
public static void main(String[] args) {
MyYield myYield1 = new MyYield();
MyYield myYield2 = new MyYield();
new Thread(myYield1,"a").start();
new Thread(myYield2,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ",start");
Thread.yield();
System.out.println(Thread.currentThread().getName() + ",over");
}
}
线程强制执行join
- join合并线程,此线程执行完再执行其他线程,其他线程阻塞
- 类似于插队,霸占所有资源完成任务
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 77; i++) {
System.out.println("插队,霸占所有资源" + i);
}
}
public static void main(String[] args) throws InterruptedException {
//启动线程
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程
for (int i = 0; i < 1000; i++) {
//在200以前是CPU调度多线程执行,20后是join执行,霸占资源
if (i == 20){
thread.join();
}
System.out.println("main:" + i);
}
}
}
线程状态观测
Thread.State
,状态为以下之一:
NEW
:暂未启动的线程RUNNABLE
:在执行的线程BLOCKED
:被阻塞等到监视器锁定的线程WAITING
:在等待另一个线程执行特定动作的线程TIMED_WAITING
:在等待另一个线程执行动作达到指定等待时间的线程TERMINATED
:已退出的线程
//观察测试线程的状态
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("==========");//输出后线程中止
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);
//启动后状态
thread.start();
state = thread.getState();
System.out.println(state);
while (state != Thread.State.TERMINATED){
Thread.sleep(100);
state = thread.getState();//更新状态
System.out.println(state);
}
//线程停止后无法再启动
}
}
线程优先级
-
Java提供一个线程调度器监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定调度线程
-
优先级由数字表示,范围为1-10:
Thread.MIN_PRIORITY = 1;
Thread.Max_PRIORITY = 10;
Thread.NORM_PRIORITY = 5;
默认优先级
-
getPriority()
:获取优先级 -
setPriority(int num)
:改变优先级
先设置优先级再运行,设置了优先级调度还是由CPU决定
public class TestPriority {
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName() + "的优先级为:" + Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
//设置优先级,启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//最大
t4.start();
t5.setPriority(5);
t5.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "的优先级为:" + Thread.currentThread().getPriority());
}
}
输出结果
main的优先级为:5
Thread-0的优先级为:5
Thread-3的优先级为:10
Thread-4的优先级为:5
Thread-2的优先级为:4
Thread-1的优先级为:1
守护(daemon)线程
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不必等待守护线程执行完毕
- 如:后台记录,回收
setDaemon(true)
:设置为守护线程;默认为false,表示用户线程,一般线程都是用户线程
程序在运行完用户线程后结束,不需要等待守护线程运行结束
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true); //默认为false,表示用户线程,一般线程都是用户线程
thread.start(); //启动守护线程
new Thread(you).start(); //启动用户线程
}
}
//God,守护线程
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("see");
}
}
}
//你,用户线程
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println("活");
}
System.out.println("=====结束了=====");
}
}