Java多线程——线程生命周期、常用方法

生命周期

JDK1.8源代码

    /**
     * A thread state.  A thread can be in one of the following states:
     * <ul>
     * <li>{@link #NEW}<br>
     *     A thread that has not yet started is in this state.
     *     </li>
     * <li>{@link #RUNNABLE}<br>
     *     A thread executing in the Java virtual machine is in this state.
     *     </li>
     * <li>{@link #BLOCKED}<br>
     *     A thread that is blocked waiting for a monitor lock
     *     is in this state.
     *     </li>
     * <li>{@link #WAITING}<br>
     *     A thread that is waiting indefinitely for another thread to
     *     perform a particular action is in this state.
     *     </li>
     * <li>{@link #TIMED_WAITING}<br>
     *     A thread that is waiting for another thread to perform an action
     *     for up to a specified waiting time is in this state.
     *     </li>
     * <li>{@link #TERMINATED}<br>
     *     A thread that has exited is in this state.
     *     </li>
     * </ul>
     *
     * <p>
     * A thread can be in only one state at a given point in time.
     * These states are virtual machine states which do not reflect
     * any operating system thread states.
     *
     * @since   1.5
     * @see #getState
     */
    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

六状态介绍

  • new(新建状态)new关键字创建一个线程对象,它并不是处于一个执行状态,因为还没有start启动线程
  • Runnable(就绪状态) 线程对象调用start方法,才是在JVM中真正创建了一个线程,线程一经启动并不会立即执行,该状态的所有线程位于就绪线程池中,等待操作系统的资源,如:处理器,获得cpu的使用权
  • Blocked(阻塞状态) 等待一个监视器锁进入同步代码块或者同步方法,代码块/方法某一时刻只能够有一个线程执行,其他线程只能等待
  • Waiting(等待状态) Object.wait()/Thread.join()/LockSupport.park()都会使得线程阻塞,从Runnable转换到Waiting状态
  • Timed_Waiting(睡眠状态) 调用加超时参数的Object.wait(long mills)/Thread.slepp(long mills)/LockSupport.parkNano()/LockSupport.parkUntil()
  • Terminated(终止状态) 是一个线程的最终状态,线程进入到Terminated状态,意味着该线程的生命周期结束了,下面这些情况都会使得线程进入Terminated状态
  • 1)线程执行正常结束
  • 2)线程运行出错意外结束
  • 3)JVM crash

六状态转换图

图片来源于《Java并发编程的艺术》一书

常用方法

1.start()

  • 启动一个线程,将线程添加一个线程组中,线程状态会从New状态转换到Runnable状态,然后获取Cpu之后进入Running状态执行run

2. sleep()

  • sleep是一个静态方法,其中存在两个重载函数
    1.public static native void sleep(long millis) 常用
    2.public static void sleep(long millis, int nanos)
  • 使得线程进入睡眠状态,暂停执行,sleep不会放弃monitor lock的所有权
  • jdk1.5之后,jdk引入一个枚举TimeUnit类,其对sleep方法做了封装,直接使用从而时间单位换算的步骤,比如线程睡眠3h27min8sec88msec

3. yield()

  • yield表示提醒cpu调度器,我愿意放弃当前的cpu资源,(属于启发式方法),如果cpu资源不紧张的情况下,会忽略这种提示
  • 此方法不常用
  • 面试题:yield和sleep的区别
    a.jdk1.5之前,yield调用了sleep
    b.sleep使得当前线程暂停执行,不会占用cpu资源, yield只是对于cpu调度器的一个提示
    c.sleep会导致线程短暂的阻塞,yield会使得线程从运行态 -> Runnable
    d.sleep会捕获到中断异常,yield不会捕获到中断异常

4. join()

  • 含义:在线程B中join某个线程A,会使得B线程进入等待,直到线程A结束生命周期,或者达到给定的时间,在这期间线程B会处于等待状态
  • 练习:ThreadA打印1-10, ThreadB打印打印1-10,,ThreadC打印1-10, 保证按照A->B->C顺序打印
public class TestDemo3 {
    public static void main(String[] args) {
        Thread A = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + "::" + i);
            }
        });

        Thread B = new Thread(() -> {
            try {
                A.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + "::" + i);
            }
        });

        Thread C = new Thread(() -> {
            try {
                B.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + "::" + i);
            }
        });

        A.start();
        B.start();
        C.start();
    }
}

5. wait()

调用当前对象的wait()方法可使当前线程阻塞

6. notify()

调用当前对象的notify()方法可以唤醒当前对象已经阻塞的其中任意一个线程

7. notifyAll()

调用当前对象的notifyAll()方法可以唤醒当前对象已经阻塞的其中所有线程,让所有线程去抢cpu资源

  • 注意:使用wait(),notify(),notifyAll()三个方法需要让当前线程拥有当前对象的monitor lock

8. 中断方法

  • 中断 :可以理解为线程的一个标识位属性,它不会中断线程,只是线程发送的一个中断信号,表示一个运行中的线程是否被其他线程进行了中断操作。
  • 中断的作用可以参考这篇文章: 线程的中断(interrupt).
  1. interrupt() :由线程对象调用,将中断位置为true
  2. interrupted():调用interrupted会擦除中断状态位的标识
  3. isInterrupted(boolean ClearInterrupted):判断当前线程的中断状态位是否为true
    注意
    1.如果当前线程处于TERMINATED(终结)状态,即使该线程被中断过,在调用此方法时依然会返回false
    2.如果当前线程正在执行可中断方法,Java虚拟机会将该线程的中断标识擦除,然后抛出InTerruptedException,此时调用此方法会返回false
  • 可中断方法:能使当前线程进入阻塞状态,调用interrupt方法可以打断阻塞,有:Object#wait(long),wait(long),Object#wait(long, int) wait(long, int),join(),join(long),join(long,int),sleep(long),sleep(long,int)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值