线程生命周期,状态转换

在这里插入图片描述

Running阶段

这个阶段的线程已经获取到了CPU调度执行权,也就是说处于运行中状态了。

在该阶段中,线程可以向前或者向后发生转换:

  1. 由于CPU的调度器轮询导致该线程放弃执行,就会进入Runnable阶段。
  2. 线程主动调用yield,放弃CPU执行权,就会进入Runnable阶段(这种方式并不是百分百生效的,在CPU资源不紧张的时候不会生效)。
  3. 调用sleep、wait方法,进入Blocked阶段(这里讲的Blocked阶段和线程的Blocked状态需要区分开,这边讲的是一个比较广义的Blocked的阶段)
  4. 进行某个阻塞的IO操作而进入Blocked阶段
  5. 为了获取某个锁资源而加入到该锁到阻塞队列中而进入Blocked阶段
  6. 线程执行完成或者调用stop方法或者判断某个逻辑标识,直接进入Terminated阶段

wait

public interface Demo {
    /*
        Causes the current thread to wait until either another thread invokes the notify()
        method or the notifyAll() method for this object, or a specified amount of time has elapsed.
        线程调用wait方法会处于等待状态,直到另一个线程调用此对象的notify()方法或notifyAll()方法,
        或者经过指定的时间当前线程才能退出等待状态。
        
        The current thread must own this object's monitor.
        当前线程必须拥有此对象的监视器。
        
        This method causes the current thread (call it T) to place itself in the wait
        set for this object and then to relinquish any and all synchronization claims on this object.
        Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
        此方法会导致当前线程(称为T)将自身置于该对象的等待集合,然后放弃对该对象的所有同步声明。
        线程T出于线程调度目的被禁用,并处于休眠状态,直到发生以下四种情况之一:
        
        Some other thread invokes the notify method for this object and thread
        T happens to be arbitrarily chosen as the thread to be awakened.
        其他一些线程调用这个对象的notify方法,而线程T恰好被任意选择为要唤醒的线程。
        
        Some other thread invokes the notifyAll method for this object.
        其他一些线程调用此对象的notifyAll方法。
        
        Some other thread interrupts thread T.
        其他线程会中断线程T。
        
        The specified amount of real time has elapsed, more or less. If timeout is zero, however, 
        then real time is not taken into consideration and the thread simply waits until notified.
        指定的实时时间或多或少已经过去。但是,如果超时为零,则不考虑实时性,线程只是等待通知。
        
        The thread T is then removed from the wait set for this object and re-enabled for thread scheduling.
         It then competes in the usual manner with other threads for the right to synchronize on the object;
        once it has gained control of the object, 
        all its synchronization claims on the object are restored to the status quo ante - that is,
        to the situation as of the time that the wait method was invoked.
        Thread T then returns from the invocation of the wait method.
        Thus, on return from the wait method, 
        the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.
        
        然后从该对象的等待集合删除线程T,并重新启用线程调度。
        然后,它以通常的方式与其他线程竞争在对象上同步的权利;一旦它获得了对对象的控制权,
        它对对象的所有同步声明都将恢复到之前的状态——也就是说,恢复到调用wait方法时的状态。
        线程T然后从wait方法的调用返回。因此,从wait方法返回时,对象和线程T的同步状态与调用wait方法时完全相同。
        
        A thread can also wake up without being notified, interrupted,
        or timing out, a so-called spurious wakeup. While this will rarely occur in practice,
        applications must guard against it by testing for the condition that should have caused the thread to be awakened,
        and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, 
        like this one:
        
        线程也可以在没有被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。
        虽然这种情况在实践中很少发生,但应用程序必须通过测试本应导致线程被唤醒的条件来防范这种情况,
        如果条件不满足,则继续等待。换句话说,等待应该总是在循环中发生,比如:
        
        
        synchronized (obj) {
        while (<condition does not hold>)
        obj.wait(timeout);
        ... // Perform action appropriate to condition
        }
        
        (For more information on this topic, see Section 3.2.3 in Doug Lea's "Concurrent Programming in Java (Second Edition)" (Addison-Wesley, 2000),
        or Item 50 in Joshua Bloch's "Effective Java Programming Language Guide" (Addison-Wesley, 2001).
        
        (有关此主题的更多信息,请参阅Doug Lea的《Java并发编程(第二版)》(Addison Wesley,2000)中的第3.2.3节,
        或Joshua Bloch的《Effective Java Programming Language Guide》(Addison Wesley,2001)中的第50项。)。
        
        If the current thread is interrupted by any thread before or while it is waiting, then an InterruptedException is thrown.
        This exception is not thrown until the lock status of this object has been restored as described above.
        
        如果当前线程在等待之前或等待期间被任何线程中断,则会抛出InterruptedException。在如上所述恢复此对象的锁定状态之前,不会引发此异常。
        
        Note that the wait method, as it places the current thread into
        the wait set for this object, unlocks only this object; any other objects on which the current thread may 
        be synchronized remain locked while the thread waits.
        
        请注意,wait方法在将当前线程放入该对象的等待集中时,只解锁该对象;在线程等待期间,
        当前线程可以同步的任何其他对象都会保持锁定状态。
        
        This method should only be called by a thread that is the owner of this object's monitor. 
        See the notify method for a description of the ways in which a thread can become the owner of a monitor.
        
        此方法只能由作为此对象监视器所有者的线程调用。有关线程成为监视器所有者的方式的描述,请参见notify方法。
    */
    public final native void wait(long timeout) 
    throws InterruptedException;
}

在这里插入图片描述

sleep

/*
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds,
subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

根据系统计时器和调度程序的精度和准确性,使当前执行的线程休眠(暂时停止执行)指定的毫秒数。
线程不会失去任何监视器的所有权。
*/
public static native void sleep(long millis) 
throws InterruptedException;

在这里插入图片描述

wait() 和sleep()有什么区别

  1. 这两个方法来自不同的类分别是wait()来自Object ,sleep()来自Thread。

  2. sleep方法不会释放锁,如果当前线程获取同步锁进入同步代码,sleep方法并不会释放锁,即使当前线程使用了sleep方法让出了cpu,其他被同步锁挡住了的线程也不能执行。wait是一个指获取同步锁进入同步代码的线程,执行wait方法后,自己暂时让出同步锁,让其他等待获取该锁的线程可以得到锁并运行,调用notify方法通知调用过wait方法的线程可以去参与获取锁的竞争了。

  3. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

  4. synchronized代码被执行期间,线程可以调用对象的wait()方法,释放对象锁标志,进入等待状态。
    

    sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。

    public class ThreadDemo implements Runnable{
    
        public void test1() throws Exception{
            synchronized(this){
                System.out.println("1");
            }
        }
        public void test2() throws Exception{
            synchronized(this){
                //Thread.sleep(2000);
                this.wait();
                System.out.println("22222222222222222");
            }
        }
        @Override
        public void run(){
            try{
                test1();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) throws Exception {
            ThreadDemo threadDemo = new ThreadDemo();
            Thread t = new Thread(threadDemo);
            t.start();
            threadDemo.do2();
        }
    }
    

2. notify() notifyAll()

  1. wait()使用notify或者notifyAlll或者指定睡眠时间来唤醒当前等待池中的线程。
  2. notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程。
public class ThreadDemo extends Thread {

    public ThreadDemo(String name){
        super(name);
    }

    @Override
    public void run(){
        for(int i = 1; i < 5; i++){
            System.out.println(this.getName() + " do" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
            ThreadDemo t = new ThreadDemo("子线程");
            t.start();
            //调用t线程的join方法,等待t线程执行完毕
            t.join();
            System.out.println("主线程");
        }
}

3. join()

等待该线程终止。
等待调用join()方法的线程结束。比如t.join(),用于等待t线程运行结束。

4. yield()

暂停当前正在执行的线程。

yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;

不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值