Java线程的实现/创建方式

  1、继承Thread类:

    Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。 启动线程的唯一方法就是通过 Thread 类的 start()实例方法。 start()方法是一个 native 方法,它将启动一个新线程,并执行 run()方法。
            

  2、实现Runnable接口:

    如果自己的类已经 extends 另一个类就无法直接 extends Thread,此时可以实现一个Runnable 接口。
            

    start()和run()方法有何区别呢?

    1)start()方法是本地方法用来启动线程,真正实现了多线程运行。这时无需等待 run 方法体代码执行完毕,可以直接继续执行下面的代码。    

    2)通过调用 Thread 类的 start()方法来启动一个线程, 这时此线程是处于就绪状态RUNNABLE, 并没有运行。

    3)方法 run()称为线程体,它包含了要执行的这个线程的内容,线程就进入了运行状态RUNNING,开始运行 run 函数当中的代码。 Run 方法运行结束此线程终止,然后 CPU 再调度其它线程。

  3、ExecutorServiceCallable<Class>Future 有返回值线程:

    有返回值的任务必须实现 Callable 接口,类似的,无返回值的任务必须 Runnable 接口。执行Callable 任务后,可以获取一个 Future 的对象,在该对象上调用 get 就可以获取到 Callable 任务返回的 Object 了,再结合线程池接口 ExecutorService 就可以实现传说中有返回结果的多线程了。

    Callable 接口是一个与Runnable 接口非常相似的接口。Callable 接口的主要特征如下:

    1)接口:有简单类型参数,与call()方法的返回类型相对应。

    2)声明了call()方法:执行器运行任务时,该方法会被执行器执行。它必须返回声明中指定类型的对象。

    3)call()方法可以抛出任何一种校验异常,可以实现自己的执行器并重载afterExecute()方法来处理这些异常。

            

   4、基于线程池的方式

    线程和数据库连接(或类似数据库连接)这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。
            

    Java 里面线程池的顶级接口是 Executor,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 ExecutorService

            

    具体创建线程的工作由Executors完成,该类的具体功能如下:

            

    其中使用Executors创建四种常用的线程池:

    1)newCachedThreadPool

      创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。 调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中;终止并从缓存中移除那些已有 60 秒钟未被使用的线程。 因此,长时间保持空闲的线程池不会使用任何资源。

    2)newFixedThreadPool

      创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。

    3)newScheduledThreadPool

      创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

    4)newSingleThreadExecutor

      Executors.newSingleThreadExecutor()返回一个线程池(这个线程池只有一个线程) ,这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去

 

posted on 2021-12-28 10:31  池塘里洗澡的鸭子  阅读(198)  评论(0编辑  收藏  举报