我这样理解多线程之一-初识多线程

初识多线程

1 线程的基本概念理解
   为了更好的学习多线程,我们先来看看线程中的那些基本概念都代表什么含义?
   进程: 是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),意思就是每启动一个进程就会分配一个独立的内存空间。
   线程:线程是进程的一个实体,是程序运行调度和分配的基本单位。它本省并没有独立的内存空间,寄生在进程。同一个进程的多个线程之间是可以共享资源的。
   多线程:指程序运行时(一个进程)不止产生了一个线程,多线程的出现,是为了我们更加充分的利用cpu资源,如果只有一个单线程,那么系统的执行能力就会特别低下,运行效率大大降低。
看了很多大神的帖子后,我决定用自己的理解来给并发和并行做个解释:
  并行:即同时执行多个任务,是依托多核系统进行的,单核的系统是没有并行概念的。
  并发:即同一时刻执行多个任务,是依托线程的概念进行的。

   在 SMP 和多核架构出现之前,大多数计算机系统只有单个处理器。CPU 调度器通过快速切换系统内的进程,以便允许每个进程取得进展,从而提供并行假象。这些进程并发运行,而非并行运行。
随着系统线程数量从几十个到几千上万个,CPU 设计人员通过增加硬件来改善线程性能的提高系统性能。现代 Intel CPU 的每个核经常支持两个线程,而 Oracle T4 CPU 的每个核支持 8 个线程。这种支持意味着,可以将多个线程加载到处理核以便快速切换。毫无疑问,多核计算机将继续增加多核数量和硬件线程支持。
2 线程的生命周期
   既然谈到线程,那必然有其存在的规律,即生命周期,从出生到死亡…
线程可分为以下几个阶段:

  • 1>新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;
  • 2>就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;
  • 3>运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。
  • 4>等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。
  • 5>终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。
      通过上面可以看到,线程的运行围绕着一个run()方法,调用run()方法线程开始运行,运行结束,线程即终止。start()只是让程序处于就绪状态,随时准备运行。在程序运行中可抵用sleep() suspend()将程序人为干预进阻塞状态,这种状态结束后才能重新进入就绪状态。

3 线程的创建方式

  • 1、继承Thread类:
       步骤:①、定义类继承Thread;
          ②、复写Thread类中的run方法;目的:将自定义代码存储在run方法,让线程运行
          ③、调用线程的start方法:
        该方法有两步:启动线程,调用run方法。

  • 2、实现Runnable接口: 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参方法。
     实现步骤:①、定义类实现Runnable接口
          ②、覆盖Runnable接口中的run方法将线程要运行的代码放在该run方法中。
          ③、通过Thread类建立线程对象。
          ④、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
    自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程执行指定对象的run方法就要先明确run方法所属对象
          ⑤、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

  • 3、通过Callable和Future创建线程:
        实现步骤:①、创建Callable接口的实现类,并实现call()方法,改方法将作为线程执行体,且具有返回值。
             ②、创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值
             ③、使用FutureTask对象作为Thread对象启动新线程。
             ④、调用FutureTask对象的get()方法获取子线程执行结束后的返回值。

猜你喜欢

转载自blog.csdn.net/weixin_39446297/article/details/106035173