线程状态和常用方法

线程状态

1)、新建(NEW):在jvm上new出一个Thread的实例,还没有调用start()方法;

2)、运行(RUNNABLE):运行状态又分为两个状态,就绪和运行中,当CPU为线程分配时间片时,线程进入运行中状态;如果不为线程分配时间片,则进入就绪状态,等待CPU分配时间片。当然,运行中的线程调用yield()也会将线程变成就绪状态;

3)、等待(WAITING):线程调用wait()/join(),进入等待状态,需要调用notify()/notifyAll()才能被唤醒再次进入运行状态;

4)、定时等待(TIMED_WAITING):线程调用sleep(long)/wait(long)/join(long),进入定时等待状态,当达到等待时间或者调用notify()/notifyAll()时,再次进入运行状态;

5)、阻塞(BLOCKED):多个线程运行,竞争某个synchronized(内置锁)的模块,只有一个线程能获得这个锁,其他线程会进入阻塞状态,当线程获取锁时,该线程从阻塞状态编程可运行状态;

6)、结束(TERMINATED):线程执行完或者抛出异常提前结束。

查看当前服务器线程状态

线程常用方法

start()和run()

start()是真正意义上的启动了操作系统的线程,线程进入就绪队列,等待CPU分配时间片,获取到时间片后才会执行线程中的run(),start()只能执行一次,重复执行会报错;

run()本质上是业务逻辑的实现方法,所以run(),与接口实现类中的实现方法一样,可以重复执行;

package com.su.mybatis.oracle.controller;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        TestThread t1 = new TestThread();
        t1.setName("Test");
        t1.start();
        TestThread.sleep(100);
        t1.run();
        TestThread.sleep(100);
        t1.run();
    }
}


class TestThread extends Thread{
    
    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        System.out.println("线程(" + threadName + ")已启动");
    }
}

 

输出结果:

线程(Test)已启动
线程(main)已启动
线程(main)已启动

结果也验证了:1、线程启动的真正方法是start();2、run()可多次执行。

yield()

将线程从运行中状态线程变成就绪状态,让出cpu的执行权,并通知操作系统,操作系统从就绪线程中选出线程执行。可以选择原来执行yield()的线程。需要注意的是让出时间不可设定,不会释放资源。

应用场景:比如一个资源初始化方法,该方法允许多个线程同时进入,但是为了保证线程安全,只允许一个线程对这个资源进行初始化。当多个线程进入该方法时,只需要第一个线程对资源进行初始化,其他线程不需要执行,此时可以使用Thread.yield()让出cpu执行权,不进行初始化。

join()

将指定线程加入到当前线程,先执行完指定线程,再执行当前线程,理解为插队即可。

举个例子:

package com.su.mybatis.oracle.controller;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        EatRunnable e = new EatRunnable();
        Thread te = new Thread(e); 
        te.start();
//        te.join();
        System.out.println("开始睡觉...");
        Thread.sleep(3000);
        System.out.println("结束睡觉...");
    }
}


class EatRunnable implements Runnable{
    @Override
    public void run() {
        try {
            System.out.println("开始吃饭...");
            Thread.sleep(3000);
            System.out.println("结束吃饭...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

开始睡觉...
开始吃饭...
结束睡觉...
结束吃饭...

睡觉吃饭几乎是同时开始,同时结束。

加上te.join();后(去掉前面的//),输出结果:

开始吃饭...
结束吃饭...
开始睡觉...
结束睡觉...

先吃完饭,再睡觉。

 

 

如果有写的不对的地方,请大家多多批评指正,非常感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值