多线程——使用Java面向对象编程

第七章 多线程 ——Java

一、进程

1.什么是进程:

​ 继承是程序的一次动态执行过程,他对应了从代码加载、执行至完成的一个完整过程,这个过程也是程序本身从产生、发展至消亡的过程。

​ 操作系统同时管理一个计算机系统中的多个进程,让计算机系统中的多个进程轮流使用CPU资源,或者共享操作系统的其他资源。

2.进程的特点:

  • 继承是系统运行程序的基本单位。

  • 每一个进程都有自己独立的一块内存空间,一组系统资源。

  • 每一个进程的内部数据和状态都是完全独立的。

二、线程

1.什么是线程:

​ 线程是进程中执行运算的最小单位,可完成一个独立的顺序控制流程。每个进程中,必须至少建立一个线程(这个线程成为主线程)来作为这个程序的入口点。

​ 如果在一个进程中同时运行多个线程来完成不同的工作,称之为“多线程”。 是多个线程共享相同的地址空间并且共同分享同一个进程 ,这些进程可以在操作系统的管理下并发执行。

三、多线程

1.什么是多线程

  • 充分利用CPU资源:执行单线程程序时,若程序发生阻塞,CPU可能会处于空闲状态,这将会造成计算机资源浪费,而使用多线程可以在某个线程处理休眠或阻塞状态时运行其他线程,这样大大提高了资源利用率。
  • 简化编程模型:一个即长又复杂的进程可以分为多个线程,成为几个独立的运行部分,如果写成单线程程序可能需要多重循环判断,而如果使用多线程控制,每个线程仅需要实现简单的流程,简化了程序逻辑。
  • 带来良好的用户体验:由于多个线程可以交替执行,减少避免了因程序阻塞或意外情况造成的响应过慢现象。

2.如何实现多线程

ThreadThread 类支持多线程

构造方法说明
Thread()分配新的 Thread() 对象
Thread(Runnable targe)分配新的 Thread() 对象, targetrun() 方法被调用的对象
Thread(Runnable targe,String name)分配新的 Thread() 对象, targetrun() 方法被调用的对象,name 作为新线程的名称
void run()执行任务操作的方法
void start()使线程开始执行,Java虚拟机代用该线程的 run() 方法
void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
String getName()返回线程的名称
int getPriorty()返回线程的优先级
void setPriority(int newPriority)更改线程的优先级
static Thread currentThread()返回当前正在执行的线程对象的引用
boolean isAlive()测速线程是否属于活动状态
void join()等待该线程终止
void interrupt中断线程
void yield()暂停当前正在执行的线程对象,并执行其他线程

3.主线程

​ 每个进程至少有一个主线程。他是从程序开始的时候开始执行的。

  1. 主线程的重要性主要体现在以下两个方面
  • 他是产生其他子线程的线程
  • 通常它必须最后完成执行,因为它执行各种关闭动作
  1. 如何使用线程
    1. 定义一个线程,同时指明这个线程所要执行的代码,即期望完成的功能
    2. 创建线程对象

      创建线程类两种方法,一种是继承 Thread 类,另一种是实现 Runnable 接口。

      1. 继承 Thread 类创建线程
      2. 需要重写 Thread 类并重写 Thread 类的 run() 方法。因为 Thread 类的 run() 方法是线程要执行操作任务,所以线程要执行的操作代码都要写在 run() 方法中,并通过调用 start() 方法启动线程后调用。
      3. 实现 Runnable 接口创建线程
        1. Runnable 接口定义在 java.lang 包中,其中声明了一个抽象方法 run() ,即 public void run() ,一个类可以同实现 Runnable 接口并实现其 run() 方法完成线程的活动,已实现的 run() 方法成为该线程的线程体。任何实现 Runnable 接口的对象都可以作为一个线程的目标对象。
    3. 启动线程
    4. 终止线程
  2. 线程状态

    如何线程都具有五种状态,即创建,就绪,运行,阻塞,死亡状态。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jccHzFi-1622615103198)(img\线程的状态.png)]

    1. 创建状态
      - 在程序中用构造方法创建了一个线程对象后,新的线程对象就处于创建状态,此时,他已经获取了相应的资源,但还没有处于可运行的状态,这时可以通过 Thread 类的方法来设置线程对象的属性。如线程名,设置线程的优先级等。

    2. 就绪状态

      • 线程创建玩之后,就可以通过调用 start() 方法启动线程,即进入就绪状态,此时,线程将进入线程队列排队,等待CPU资源,这表明他已经具备了运行条件,在未获得CPU资源时,仍然不能真正执行。
    3. 运行状态

      • 当就绪状态的线程获得CPU资源时,即可转入运行状态,执行 run() 方法。对只有一个CPU的计算机而言,任何时空只能有一个处于运行状态的线程占用CPU,即获得CPU资源。
    4. 阻塞状态

      • 一个正在运行的线程因某种原因不能继续运行时,进入阻塞庄园。阻塞状态时一种“不可运行”的状态,而处于这种状态的线程在得到一个特定的事件后转回可运行状态。

      • 可能使线程暂停执行的条件如下:

        • 由于线程的优先级比较低,因此他不能获得CPU资源。
        • 使用 slept() 方法使线程休眠
        • 通过调用 wait() 方法,使线程等待
        • 通过调用 yield() 线程显式让出CPU控制权。
        • 线程由于等待一个文件,I/O事件被阻塞
      1. 死亡状态
        • 一个线程的 run() 方法运行完毕,线程则进入死亡状态,处于死亡状态的线程不具有继续运行的能力。
4.线程的优先级

​ 懂同一时刻有一个或得个线程处于可运行状态时,他们需要排队等待CPU资源,每个线程会自动获得一个线程的优先级,优先级的高低反映线程的重要或紧急程度。

​ 线程的优先级用1~10表示,1表示优先级最低,10表示优先级最高,默认值是5。

5. 线程的休眠

​ 在程序程序组允许一个线程进行短暂休眠,直接调用 Thread.sleep() 方法即可实现线程的休眠

sleep() 方法会让当前线程休眠(停止执行)mills毫秒,线程由运行中的状态进入不可运行状态,睡眠时间过后会再次进入就绪状态,需要判断他是否死亡 需要处理 InterruptedException 异常。

5. 线程的强制运行

join() 方法使当前的线程暂停执行,等待调用该方法的线程结束后再继续执行本线程。它有三个重载方法

public final void join()
public final void join(long mills)
public final void join(long mills,int nanos)

需要判断他是否死亡 需要处理 InterruptedException 异常。

6.线程的礼让

yield() 方法可以暂停当前的线程执行,允许其他线程具有相同优先级的线程获得运行机会,该线程仍处于就绪状态,不转为阻塞状态,此时相同现在其他相同或更高优先级的线程执行,如无其他相同或更高优先级的线程,则该线程继续执行。

7.线程的同步

​ 有一些同时运行的线程需要共享数据,此时就需要考虑其他线程的状态和行为,否则不能保证程序运行结果的准确性。

​ 如何实现:

​ 一个线程类如果是通过实现 Runnable 接口实现的,那么类中的属性有可能被多个该类的线程对象共享,就有可能引发线程不同步的问题。

采用线程同步有两种方式

  1. 同步方法
    使用 synchronized 修饰的方法控制对类成员的访问。每个类实例对应一把锁,方法一旦执行,就独占该锁。直到从该方法返回时才将锁释放,从此以后被阻塞的线程方能获得该锁,重新进入可执行状态。

    //通过哎方法声明中加入synchronized关键字来声明同步方法
    	访问修饰符 synchronized 返回值类型 方法名 (参数列表){//省略方法体。。。。。。}
    或者
        synchronized 访问修饰符 返回值类型 方法名 (参数列表){//省略方法体。。。。。。}
    

    在语法中:

    synchronized 是同步关键词。

    ​ 访问修饰符是指 publicprivate 等。

  2. 同步代码块

    代码块即使用{}括起来的一段代码,使用 synchronized 关键字修饰的代码块,成为同步代码块。

    synchronized (syncObject){
    	//需要同步的代码
    }
    

    synchronized 块中的代码必须获得对象 syncObject 的锁才能执行,具体机制和代码同步一致。可以制定上锁的对象。

  3. 常见类型对比

    1. Hashtable && HashMap

      • Hashtable

        ​ 1. 继承 关系

        ​ 实现了Map接口,Hashtable继承Dictionary

        ​ 2. 线程安全,效率较低

        ​ 3. 键和值都不允许为null

      • HashMap

        1. 继承关系

        ​ 实现了Map接口,继承AbstractMap

        1. 非线程安全,效率较高

        2. 键和值都允许为null

    2. StringBuffer && StringBuilder

      前者线程安全,后者非线程安全

    四、总结

在这里插入图片描述

    2. 非线程安全,效率较高

    3. 键和值都允许为**null**
  1. StringBuffer && StringBuilder

    前者线程安全,后者非线程安全

四、总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顾拾柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值