今天我们来说说线程生命周期和常用API:我们需要非常清楚的知道线程的各种状态,比如在排查线程的原因时程序运行缓慢,我们可以使用你需要看看它是否被阻塞在某个地方;此外,这也是面试中很受欢迎的问题。基本内容回答不好,怕是直接挂了。本文分为两部分,1.线程的6大状态;2、多线程常用的API:join()wait()notify()yield()sleep()currentThread()getName()getId()getPriority()setPriority()stop()线程状态关于线程的状态,有网上各种说法,比较流行的有5、6条。5州的版本我没有找到理论依据。如果谁有明确的想法,欢迎留言指出。我这里写的是基于java.lang.Thread的源码。线程有以下六种状态:publicenumState{NEW,RUNNABLE,BLOCKED,WAITTING,TIMED_WAITTING,TERMINATED;}首先我们来看上图。1.新建一个还没有启动的线程,处于这个状态。指的是线程刚刚创建,还没有启动的时候,比如刚刚创建了一个新的线程。我的线程myThread=newMyThread();2.Runnable一个线程正在Java虚拟机中执行,但它可能正在等待来自操作系统的其他资源,比如处理器。然后,下一步就是启动线程,也就是调用thread()方法的start。我的线程.start();线程启动后进入Runnable状态。这时候,所有的线程都会加入到一个等待队列中,等待“CPU调度”。如果CPU资源被抢占,则执行;如果没有,就等待,等待当前正在执行的线程完成它可以执行的时间片,然后再抢占它。需要注意的是,这里等待的一般是系统资源,而不是锁或者其他阻塞。3.BlockedThread状态为阻塞等待监视器锁的线程。处于阻塞状态的线程正在等待监视器锁进入同步块/方法或在调用wait()对象后重新进入同步块/方法。这里给出一个非常明确的用例,如果被锁在外面就叫做阻塞。所以这里至少要有2个线程。4.Waiting处于等待状态的线程正在等待另一个线程执行特定的动作。具体原因是什么?由于调用以下方法之一,线程处于等待状态:Object.waitwithnotimeoutThread。joinwithnotimeoutLockSupport.park所以,当wait()、join()、park()方法被调用时,线程进入等待状态。这里的等待状态是没有时间限制的,可以无限期的等待。。。所以需要有人来唤醒它:如果是通过wait()进入等待状态,需要有notify()或者notifyAll()方法来唤醒它;如果是通过join()进入等待状态,则需要等待目标线程运行完毕。比如在生产者-消费者模型中,当没有产品时,消费者需要等待,等待生产者生产产品并发送notify()。我们将在下一篇文章中详细介绍。5.Timed_waiting导致这个状态如下:Thread.sleepObject.waitwithtimeoutThread.joinwithtimeoutLockSupport.parkNanosLockSupport.parkUntil实际上是根据之前的状态给出一个具体的时间限制。然后当时间结束时,线程被释放。6.Terminated已经退出的线程处于这种状态。有3种情况会终止线程:执行完所有代码,正常结束;强制结束,比如调用stop()方法,现在已经弃用;抛出未捕获的异常。线程一旦死亡,就无法复活。如果在死线程上调用start()方法,程序将抛出java.lang.IllegalThreadStateException。接下来说说多线程中常用的11个API。原料药1。join()join()方法会强制线程执行,它会一直让它执行。比如上一篇文章的例子是两个线程交替执行,那么我们应该改成调用小七thread.join(),那么效果就是先输出小七666。publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){for(inti=0;i<100;i++){System.out.println("小七666:"+i);}}publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(newMyRunnable());t.start();t.join();for(inti=0;i<100;i++){System.out.println("主线程"+i+":启捷666");}}}所以join()可以保证某个线程先执行,一直让它执行,然后回到公平竞争状态。join()方法其实是用wait()实现的,我们来看看这个方法。2、wait()和notify()wait()其实不是Thread类的一个方法,而是Object中的一个方法。该方法是让当前对象等待,直到另一个对象调用notify()或notifyAll()。当然我们也可以设置一个等待时间,过了这个时间对象就会自动唤醒。4.yield()yield本身的中文意思就是yield,用在这里很合适。yield()表示当前线程主动让出CPU资源,然后我们一起抢。注意这里真的只是一个瞬间,从“执行”到“等待CPU分配资源”,然后所有线程一起抢占资源。5.sleep()顾名思义,这个方法就是让当前线程休眠一段时间,比如myThread.sleep(1000);//休眠1秒就会抛出InterruptedException,所以trycatch.6.currentThread()返回对当前正在执行的线程对象的引用。该方法是获取当前线程对象。注意是静态方法,所以直接通过Thread类调用。例如打印当前线程System.out.println(Thread.currentThread());在前面的例子中,它会输出:Thread[Thread-0,5,main]Thread[main,5,main]是的,它返回的值也是Thread类型。7.getName()这个方法可以得到当前线程的名字。这个名字可以自己设置,例如:Threadt=newThread(newMyRunnable(),"益气雪");8.getId()该方法是获取线程的Id。9.getPriority()线程也有优先级~虽然优先级不能100%保证更高级的线程先执行,但是有更大的概率先执行。优先级范围是1-10,看源码:/***Theminimumprioritythatathreadcanhave.*/publicfinalstaticintMIN_PRIORITY=1;/***Thedefaultprioritythatisassignedtoathread.*/publicfinalstaticintNORM_PRIORITY=5;/***Themaximumprioritythatthreadcanhave.*/publicfinalstaticintMAX_PRIORITY=10;如果不在这个范围内,JDK会抛出IllegalArgumentException()的异常。10.setPriority()当然我们也可以自己设置某个线程的优先级。设置的优先级也需要在1-10的指定范围内。如果不在这个范围内,就会抛出异常。11.stop()最后说一下stop()方法,这也是上面提到的一种强制停止线程的方法,但是现在已经弃用了,因为它会造成一些线程安全问题。好了,以上就是线程状态和常用API的介绍。相信大家看完之后应该对线程的整个过程有了清晰的认识。其实还有很多细节我没有展开。毕竟这是多线程的第二讲。让我们花时间了解更深入的内容。本文转载自微信公众号“码农田小七”,可通过以下二维码关注。转载本文请联系码农田小七公众号。
