【多线程】(三)java.lang.Thread小结

一、前言

        学习多线程的第一步骤已经介绍过,关于进程与线程,属于概念性的东西,那么第二步就肯定是“Hello World”实践性地上手练习了,最终要的Thread类核心方法,我做了一幅图,如下:

   

       Thread类最常用到的几个方法,我做了分类汇总,如上所示,基础中的基础概念。至于每一个具体的方法,需要经过思考、代码实战之后,才能很好地运用自如,推荐《Java多线程编程核心技术》这本书,我只做宏观总结,细节的点,就不重复制造轮子了。


二、基础

       基本的Thread常用方法能够熟练使用之后,简单对jdk中java.lang.Thread这个类做个简单介绍:

       1.https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#field_summary  

       2.https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html 

       如上,分别是Oracle官方对Thread类、Runnable接口的文档介绍(Thread类实现Runnable接口)


       其中,java.lang包下的几个Thread相关类,如下:

        

     (该系列博客之后会分别介绍“ThreadLocal”、“ThreadDeath”、“ThreadGroup”的用法)


      一、Runnable Interface

      由于Thread类继承自Runnable接口,参考Runnable接口文档:

     (0)起源于jdk 1.0

     (1)All Known Subinterfaces:(子接口)

       RunnableFuture<V>, RunnableScheduledFuture<V>

     (2)All Known Implementing Classes:(jdk中实现类)

      AsyncBoxView.ChildState, ForkJoinWorkerThread, FutureTask, RenderableImageProducer, SwingWorker, Thread, TimerTask

     (3)方法只有一个!

//When an object implementing interface Runnable is used to create a thread, starting the thread causes the object's run method to be called in that separately executing thread.
//The general contract of the method run is that it may take any action whatsoever.
void run()
      看过源码之后才发现,start()让线程开始在CUP排队准备执行,而线程真正跑起来的方法run(),竟然是在Runnable()接口当中定义。

     (4)summary(原生英文品起来会更有味道)

      The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run.
      This interface is designed to provide a common protocol for objects that wish to execute code while they are active. For example, Runnable is implemented by class Thread. Being active simply means that a thread has been started and has not yet been stopped.
       In addition, Runnable provides the means for a class to be active while not subclassing Thread. A class that implements Runnable can run without subclassing Thread by instantiating a Thread instance and passing itself in as the target. In most cases, the Runnable interface should be used if you are only planning to override the run() method and no other Thread methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.

       至此,对于Thead的实现接口Runnable就都了解了。


       二、Thread Class(since jdk 1.0)

public class Thread extends Object implements Runnable
       如上,是jdk源码中Thread类的信息,详细解释如下:

     (1)嵌套类(接口)

        1.Thread.State (since jdk 1.5)

        线程状态类,oracle官方解释:https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.State.html 

        这个State类,其实也正是在描述线程的生命周期,周期中各个状态之间的转化,将会在本系列后续博客中讲解。

         2.Thread.UncaughtExceptionHandler<interface>(since jdk 1.5)

        当一个线程即将终止,由于一个未捕获的异常,Java虚拟机将使用Thread.getUncaughtExceptionHandler()查询线程的UncaughtExceptionHandler,并调用处理程序的uncaughtException方法,将线程和异常作为参数传递。 如果一个线程没有显式地设置它的UncaughtExceptionHandler,那么它的ThreadGroup对象作为它的UncaughtExceptionHandler。 如果ThreadGroup对象没有处理异常的特殊要求,它可以将调用转发给默认的未捕获的异常处理程序。

        

      (2)字段

       MAX_PRIORITY  //线程优先级的最大值

       MIN_PRIORITY   //线程优先级的最小值

       NORM _PRIORITY   //线程优先级的默认值

      

      (3)构造函数

        结合Oracle官方文档,以及《Java多线程编程核心技术》一书,线程类Thread的构造函数,可用方式8种。参考如下:

Thread()
//Allocates a new Thread object.
Thread(Runnable target)
//Allocates a new Thread object.
Thread(Runnable target, String name)
//Allocates a new Thread object.
Thread(String name)
//Allocates a new Thread object.
Thread(ThreadGroup group, Runnable target)
//Allocates a new Thread object.
Thread(ThreadGroup group, Runnable target, String name)
//Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group.
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
//Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size.
Thread(ThreadGroup group, String name)
//Allocates a new Thread object.
        其中Runnable接口、name属性、ThreadGroup、stackSize会选择性搭配,作为其构造参数,在最上面的思维导图可见,新建线程的方式一般分为两种:1.继承Thread类,2.实现Runnable接口。随着使用越来越深,以及业务场景,可以选择合适的Thread构造方式。
      

     (4)方法

       在我看来,这部分也是在使用Thread类中,最需要掌握的地方。学习Thread基础的过程中,随着jdk的版本演进,有新的方法被加入进Thread中,有老的方法被顶替掉,下面就从jdk的演进角度,对Thread中方法进行梳理:

       1.核心方法

        除了上述“思维导图”中列举出的6大类方法,需要补充的几个方法如下:

        1)wait() & notify()

        2)join()

        3)run()

        4)toString() //返回该线程的字符串表示,包括线程的名称、优先级和线程组。

        都很简单,具体功能后续博客会介绍。


       2.Deprecated(废弃的方法)

       1)resum() & suspend

        之所以suspend()和resum()方法被废弃,因为他们会导致线程死锁,官方文章给出了考虑这两个方法被废弃的原因:    

         https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html   

       2)countStackFrames()

       这个方法依赖了suspend()方法,所以……

       3)stop()

       这种方法本质上是不安全的。 使用Thread.stop停止线程会导致它解锁所有已锁定的监视器(作为未检查的ThreadDeath异常向上传播的自然结果)。 如果之前由这些监视器保护的任何对象处于不一致状态,则损坏的对象对其他线程变得可见,可能导致任意行为。 停止的许多用途应该被代码替换,该代码简单地修改一些变量以指示目标线程应该停止运行。 目标线程应该定期检查这个变量,并且如果变量指示它将停止运行,则从其run方法有序地返回。 如果目标线程长时间等待(例如,在条件变量上),则应使用中断方法来中断等待


      3.继承自class java.lang.Object的方法

equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      

     (5)异常

       1.IllegalArgumentException

       2.InterruptedException

       3.SecurityException

       4.NullPointerException

       可见,Thread中的方法在调用过程会引发形形色色的异常,主要都是方法细节处理不当造成的,顺便介绍一下,interrupt()方法,搭配InterruptException,是终止线程的一个非常好的方法。


       最后,引申一个概念:java.util.concurrent并发包,这是在jdk1.5的时候引入的包,以及相关接口Callable<V>,都是并发编程中非常重要的概念,这里点一下,多线程系列博客的后续章节会进行详细讲解。


       如上所述,通过java.lang.Thread类的学习,对多线程的基本概念、最常用的方法就有了大致认识了。





猜你喜欢

转载自blog.csdn.net/u013047584/article/details/78630261