Java教程

线程的状态及方法

本文主要是介绍线程的状态及方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 线程的状态及状态转换
    • 线程状态
      • 新建状态(NEW)
      • 就绪状态(RUNNABLE)
      • 运行状态(RUNNING)
      • 阻塞状态(BLOCKED)
      • 等待状态(WAITING)
      • 睡眠等待(TIMED_WAITING)
      • 终止状态(TERMINATED)
    • 线程状态转换
  • 线程方法
    • start():启动线程
    • run():子线程执行体
    • yield():线程让步
    • sleep():线程睡眠
    • join():线程同步
    • interrupt():**中断线程**
    • deamon:守护线程
    • Priority:线程优先级


线程的状态及状态转换

线程状态

jdk中提供了线程的状态,在Thread类中提供了一个内部的枚举类:State

public enum State {
        NEW,//新建状态
        RUNNABLE,//就绪状态
        BLOCKED,//阻塞状态
        WAITING,//等待状态
        TIMED_WAITING,//睡眠等待状态
        TERMINATED;//终止状态
    }

新建状态(NEW)

用new语句创建的线程处于新建状态,此时和其他对象一样,在堆中仅仅给他分配了内存

就绪状态(RUNNABLE)

当一个线程创建后,调用了start方法,线程状态就进入到就绪状态,处于就绪状态的线程意味着所有需要的资源已经装备就绪,等待CPU的调用,CPU的调度是由操作系统控制的,用户无法操控

运行状态(RUNNING)

处于运行状态的线程占用CPU资源,执行程序代码,只有处于就绪状态的线程才能有机会进入到运行状态
1、如果一个时间片用完或者调用yield方法,线程会从运行状态进入到就绪状态
2、如果线程已经执行结束了,线程会从运行状态进入终止状态
3、如果线程执行过程中因为等待一些资源而进入阻塞状态(WAITING、TIME_WAITTING、BLOCKED)

阻塞状态(BLOCKED)

进入这种阻塞状态的原因可以是:线程期望进入同步方法或者同步代码块(Synchronized),尚未获取到锁资源的情况下,可以从运行状态进入到blocked状态

等待状态(WAITING)

如果调用wait()方法,就进入到waiting状态,即调用wait()会触发线程从运行状态进入到阻塞状态而无法执行,直到其他线程发出notify或notifyAll这个方法,此时线程才会从waiting状态进入到blocked状态,进而进入就绪状态

睡眠等待(TIMED_WAITING)

如果线程调用sleep(long)、join(long)、wait(long)等方法是,会触发线程进入到TIMED_WAITING状态,即指定了阻塞的时间,到达了给定的时间后就可以继续进入就绪状态等待CPU的调度

终止状态(TERMINATED)

当线程退出run()方法时,线程就进入了终止状态,该状态是结束线程的声明周期

线程状态转换

在这里插入图片描述
一个线程的生命周期中需要的状态:NEW、RUNNABLE、RUNNING、TERMINATED四个状态,当线程需要响应特定资源时,进入到阻塞状态:BLOCKED、WATING、TIMED_WAITING状态

线程方法

start():启动线程

start方法作用是用来启动一个新线程,start方法需要首先调用,start方法是不能被重复调用的

 public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
      
            }
        }
    }

    private native void start0();

tart方法的实现是调用了一个native的方法,本质上java创建的多线程其实是有操作系统所提供的多线程方式来创建的
start方法启动子线程是通过调用系统提供的方式来启动线程

run():子线程执行体

run方法中是子线程的执行体
run方法和普通的成员方法一样,可以被重复调用,如果在当前线程调用执行run(),是不会启动新线程

yield():线程让步

public static native void yield();

yield方法是定义在Thread类下的静态方法
当线程中调用yield方法,会让当前正在执行的线程由”RUNNING“状态进入到”RUNABLE状态“,线程锁占用的锁是不会释放的
yield让出CPU的执行权,当让给谁,是由系统决定的,系统会让具有相同优先级的或更高优先级的线程获取CPU执行权,如果没有相应优先级的线程,当前线程就会立即执行

sleep():线程睡眠

是让线程休眠,而且是哪个线程调用,就是那个线程休眠
sleep方法是Thread类下的静态方法,该方法执行过程中会抛出InterruptedException异常,即可以终止异常
sleep所在的线程休眠期间,线程会释放掉CPU资源给其他线程,但如果当前线程本身持有锁,锁是不会释放的,
线程会由”RUNNING“状态进入到TIMED_WAITING状态,当到达休眠时间或者是被中断掉休眠,就会从睡眠状态进入到就绪状态,从而等待CPU的调用
方法:
sleep(long millis)
sleep(long millis, int nanos)
这两个方法都是Thread类的静态方法,不属于某个对象

 //设置休眠的时间,单位是毫秒
   public static native void sleep(long millis) throws InterruptedException;

   //设置休眠时间 毫秒和纳秒
    public static void sleep(long millis, int nanos) throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

join():线程同步

暂停当前线程,等待子线程的执行,也称之为线程合并,join方法特点将并行执行的事情合并为串行执行。
例如:如果在ta线程中调用tb.join(),则让ta线程停止执行,并让tb线程先执行,直到tb线程执行完毕,ta线程才能继续执行

interrupt():中断线程

用来中断当前线程,终止处于阻塞状态的线程
interrupt方法是在Thread类中的一个普通方法,由对象调用该方法

方法:
boolean isInterrupted():判断线程是否发生中断,true:表示中断 false:非中断
interrupt():中断方法

方法特点:
interrupt方法执行是对中断标志位做了修改
1、如果线程当前是可中断的阻塞状态(调用sleep、join、wait等方法会导致线程进入到阻塞状态:WAITING/TIMED_WAITING/BLOCKED),
在任意的其他线程调用t.interrupt方法,那么线程会立即抛出一个InterruptedException异常,退出阻塞状态
2、如果线程t当前存储于运行状态,则调用t.interrupt()方法,线程会继续执行,直到发生了阻塞(调用sleep、join、wait)后立即抛出异常,跳出阻塞状态,Interrupt并不会终止处于“运行状态”的线程,其仅仅是对标志位做了修改

 Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 0;
                while (i<10){
                    System.out.println(i++);
                }
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("睡眠结束");
            }
        });
        thread.start();
        thread.interrupt();

    }

在这里插入图片描述

deamon:守护线程

方法:
//void setDaemon(boolean on) 设置守护线程 参数:true:设置为守护线程 false:非守护线程。默认false
// boolean isDaemon() 判断当前线程是否是守护线程:true:表示守护线程 false:用户线程

java中有两种线程,用户线程和守护线程,可以通过isDaemon()来区分线程是否是守护线程
用户线程一般是用来执行用户级任务
守护线程也称之为“后台线程”,服务于用户线程,一般用来执行后台任务 例如“:垃圾回收线程是单独用来处理无用对象的回收的, 负责垃圾回收的线程就是守护线程

守护线程的生命周期:
守护线程的生命周期是依赖于用户线程,当用户线程存在,守护线程就会存活,当用户线程生命终止,守护线程的也会随之消亡

Priority:线程优先级

线程优先级:指导线程的执行的先后顺序的
方法:
//int getPriority() 获取线程的优先级
//setPriority(int newPriority) 设置线程优先级 newPriority必须在1~10之间的整的,默认的是5
优先级特点:
1、java线程的优先级并不绝对,他所控制的是执行的优先机会,优先级的决定权在操作系统,java设置的优先级只能是被优先执行的概率会高一些,并不绝对
2、java中优先级共有10级,分为1-10,数值越大,表明优先级越高,一般普通的线程优先级是5
3、优先级具有继承性,如果一个线程B在另一个线程A中创建出来,那么线程B的优先级和线程A保持一致

这篇关于线程的状态及方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!