【并发编程基础】线程基础(常用方法、状态)

文章放置于:https://github.com/zgkaii/CS-Notes-Kz,欢迎批评指正!

1 线程状态简述

Java线程在运行的生命周期中可能处于如下6种不同的状态,在给定的一个时刻,线程只能处于其中的一个状态。

线程状态 说明
NEW 初始状态,线程刚被创建,但是并未启动(还未调用start方法)。
RUNNABLE 运行状态,JAVA线程将操作系统中的就绪(READY)和运行(RUNNING)两种状态笼统地称为“运行中”。
BLOCKED 阻塞状态,表示线程阻塞于锁。
WAITING 等待状态,表示该线程无限期等待另一个线程执行一个特别的动作。
TIMED_WAITING 超时等待状态,不同于WAITING的是,它可以在指定时间自动返回。
TERMINATED 终止状态,表示当前状态已经执行完毕。

线程在自身的生命周期中,并不是固定地处于某个状态,而是随着代码的执行在不同的状态之间进行切换。

2 Thread类常用方法

2.1 start()与run()

void start()启动一个新线程,在新的线程运行run方法中的代码。

@Slf4j
public class ThreadTest {
   
    public static void main(String[] args) {
   
        Thread thread = new Thread() {
   
            @Override
            public void run() {
   
                log.debug("running...");
            }
        };
        thread.setName("new thread");
        thread.start();
        log.debug("main thread");
    }
}

输出结果如下,可见run()方法里面内容的调用是异步的。

14:06:43.754 [main] DEBUG com.kai.demo.basic.ThreadTest - main thread
14:06:43.754 [new thread] DEBUG com.kai.demo.basic.ThreadTest - running...

将上面代码的thread.start()改为 thread.run(),输出结果如下,可见 run()方法里面内容的调用是同步的。

14:08:17.974 [main] DEBUG com.kai.demo.basic.ThreadTest - running...
14:08:17.979 [main] DEBUG com.kai.demo.basic.ThreadTest - main thread

2.2 sleep()与yield()

2.2.1 sleep()

调用 sleep()会让当前线程从 RUNNING进入TIMED_WAITING状态(超时等待)。sleep()方法导致了程序暂停执行指定的时间,让出CPU给其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放锁

Tips:sleep()中指定的时间是线程暂停运行的最短时间,不能保证该线程睡眠到时后就开始立刻执行。

public class TimeWaitingTest extends Thread {
   
    @Override
    public void run() {
   
        for (int i = 0; i < 10; i++) {
   
            if ((i) % 5 == 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 TimeWaitingTest().start();
    }
}

运行结果:

开启线程数为:0
0 线程睡眠1秒!
1 线程睡眠1秒!
2 线程睡眠1秒!
3 线程睡眠1秒!
4 线程睡眠1秒!
开启线程数为:5
5 线程睡眠1秒!
6 线程睡眠1秒!
7 线程睡眠1秒!
8 线程睡眠1秒!
9 线程睡眠1秒!

可见,线程睡眠到时间就会自动苏醒,并返回到Runnable(可运行)中的就绪状态。

Tips:建议用 TimeUnit 的 sleep() 代替 Thread 的 sleep()来获得更好的可读性。

2.2.2 yield()

调用yield()静态原生方法,也能暂停当前线程,其与sleep()有何异同呢?

  • sleep(long)方法会使线程转入超时等待(TIMED_WAITING)状态,时间到了之后才会转入就绪状态。而yield()方法不能指定时间,不会将线程转入TIMED_WAITING状态,而是强制线程进入READY状态,从而让其它具有相同优先级的等待线程获取执行权。
  • 使用sleep(long)方法需要处理异常InterruptedException ,而yield()不用处理异常。

sleep()与yield()的共同点就是:

  • 两者都不释放锁、释放CPU资源

2.3 wait()

线程中调用Object.wait()方法时,当前线程就会进入阻塞状态,会释放CPU资源和释放同步锁(类锁和对象锁)。直到其他线程调用此对象的notify()方法或 notifyAll()方法。

wait是Object类中的方法,方法内部很简单,使用native方法实现:

	// 进入WAITING状态
	public final void wait() throws InterruptedException {
   
        wait(0);
    }
	// 进入TIMED_WAITING状态
	public final native void wait(long timeout) throws InterruptedException;

    // 进入TIMED_WAITING状态
    public final void wait(long timeout, int nanos) throws InterruptedException {
   
        if (timeout < 0) {
   
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) {
   
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
        if (nanos > 0) {
   
            timeout++;
        }
        wait(timeout);
    }    

wait()方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。

如果当前线程在等待之前或在等待时被任何线程中断,则会抛出 InterruptedException异常。

使用案例:

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();
                        } catch (InterruptedException e) {
   
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "=== 从WAITING状态醒来,获取到锁对象,继续执行");
                    }
                }
            }
        }, "线程A").start();

        new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                while (true) {
    //每隔3秒 唤醒一次
                    try {
   
                        System.out.println(Thread.currentThread().getName() + "‐‐‐ 等待3秒钟");
                        Thread.sleep(
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值