【了解Java线程状态及线程等待操作】


活动地址:CSDN21天学习挑战赛

目录

​一、线程状态(Thread.state)概述

1.1 六种线程状态

1.2 线程状态关系图

二、Timed Waiting (计时等待)

三、Waiting (无限等待)

四、线程等待的wait和sleep操作


​一、线程状态(Thread.state)概述

1.1 六种线程状态

线程状态 发生条件
NEW创建状态 线程刚被创建,但是并未调用start方法启动。
Runnable可运行状态

调用start方法后,线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready);

就绪状态的线程在获得CPU时间片后变为运行中状态(running)。

Blocked阻塞状态 线程阻塞于锁。
Timed Waiting计时等待 调用带有超时参数的方法(常见的有Thread.sleep 、Object.wait)进入等待,当超过时间时被自动唤醒。
Waiting无限等待 等待另一个线程执行动作,进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒
Teminated终止状态 因为run方法正常退出或者因为没有捕获的异常终止了run方法而死亡。

1.2 线程状态关系图

        线程的创建及终止比较容易理解,下面主要阐述线程从Runnable(可运行)状态与非运行状态之间的转换问题 ,即Timed Waiting计时等待、Waiting无限等待两种状态。

二、Timed Waiting (计时等待)

        “计时等待”作用:

                在run方法中添加了sleep( 数值)语句,相当于强制当前正在执行的线程休眠(暂停执行),以“减慢线程”,可以解决线程执行太快,现象不明显等问题。 

        举例1:设计一个计数器,计数到100,在每个数字之间暂停1秒,每隔10个数字输出一个字符串

  public class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 100; i++) {
            if ((i) % 10 == 0) {
                System.out.println("‐‐‐‐‐‐‐" + i);

            }
            System.out.print(i);
            try {
                Thread.sleep(1000);
               System.out.print("    线程睡眠1秒!\n");  
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        new MyThread().start();  //启动线程
    }
}

        总结:1)将Thread.sleep()的调用放线程run()之内,使得该线程执行过程中会暂停;

                   2)sleep与锁无关,线程睡眠到规定时间后自动被唤醒,并返回到Runnable(可运行)状态;

                   3)sleep()中指定的时间是线程不会运行的最短时间,即sleep()方法不能保证该线程睡眠到期后就开始立刻执行。

三、Waiting (无限等待)

        waiting等待体现的是多个线程间的通信:多个线程会争取锁,同时相互之间又存在协作关系 。

        当多个线程协作时,如A,B两个线程,如果A线程在Runnable(可运行)状态中调用了wait()方法那么A线程就进入了Waiting(无限等待)状态,同时失去了同步锁。假如这个时候B线程获取到了同步锁,在运行状态中调用了notify()方法,那么就会将无限等待的A线程唤醒。注意是唤醒,如果获取到锁对象,那么A线程唤醒后就进入Runnable(可运行)状态如果没有获取锁对象,那么就进入到Blocked(锁阻塞状态)

        举例2:A线程调用wait()方法后,观察A,B两个线程的运行顺序

package Thread;

public class WaitingTest{
	public static Object obj = new Object();
public static void main(String[] args) {
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					synchronized (obj) {
						try {
							System.out.println(Thread.currentThread().getName()+ "===获取到锁对象,调用wait方法,进入waiting状态,释放锁对象");
							obj.wait();//无限等待
							//obj.wait(5000);//计时等待5s,时间到后自动被唤醒
						}catch(InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()+ "===从waiting状态醒来,获取到锁对象,继续执行");
					}
				}
			}
		},"A等待线程").start();
		
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				
				try {
					System.out.println(Thread.currentThread().getName()+ "------等待3秒");
					Thread.sleep(3000);
				}catch(InterruptedException e) {
					e.printStackTrace();
				}
				
				synchronized (obj) {
					
					System.out.println(Thread.currentThread().getName()+ "------获取到锁对象,调用notify方法,释放锁对象");
					obj.notify();
				}
			}
		},"B唤醒线程").start();
		
	}	
}

四、线程等待的wait和sleep操作

        线程等待的方法有三种:①Thread.sleep(long millis);②Object.wait(long timeout);③wait();【也称为“唤醒wait”】

        其中,②、③的wait方法必须在同步块中使用,即

                                                synchronized (obj) {

                                                        ......

                                                        obj.wait();

                                                        ......

                                                }

        Java中wait和sleep的区别,参考博文:java中wait和sleep的区别

猜你喜欢

转载自blog.csdn.net/m0_46427461/article/details/126243465