多线程

Posted macht

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程相关的知识,希望对你有一定的参考价值。

进程接口Runnable是一个函数式接口,它的子类有Thread和任何实现它的类。但是由于它是一个函数式接口想要启动必须借助Thread的start方法,因此这里就用到了装饰器模式。把用户实现的Runnable类放入Thread方内部就能在不改变原对象代码的基础上给他扩展出start方法。

线程相关概念

进程和线程

  • 进程:正在运行的程序,一旦程序启动,操作系统就会为进程分配系统资源(内存、CPU),一个软件可能有一个或多个进程。
  • 线程:一个进程可能需要执行多个任务,多个任务的执行需要同时运行,相互不影响,每个任务由一个线程执行,一个进程可能包含一个或多个线程。

    进程和线程的区别:

  1. 一个进程包含多个线程
  2. 进程属于重量级单位,线程属于轻量级单位
    进程的创建、启动、销毁需要更多的系统资源,比较复杂
    线程相对来说占用资源更少,更容易使用
    线程间通信比进程间容易,快速
  3. 进程之间是相互独立,多个线程可以共享所在进程的堆内存,每个线程有独立的栈和寄存器

    多进程和多线程:

    多进程就是多个进程同时执行,现代操作系统是多进程的,一个CPU一个时间点只能运行一个进程,CPU需要在多个进程间来回切换,因为CPU速度快,所以用户感觉多个进程同时执行。
    多线程是一个进程的多个任务,CPU执行进程时,会在多个任务之间来回切换,会给每个任务一定执行时间(CPU时间片),线程就是CPU分配时间片的单位。

同步和异步

  • 同步
    单线程执行,多个任务需要排队执行
    类似:银行的排队
  • 异步
    多线程执行,启动另一个线程执行任务,当前线程执行其他任务,另一个线程执行完后通知当前线程
    类似:找另一个人去银行办业务,自己做别的事情

并行和并发

  • 并行
    多个CPU,每个CPU执行一个线程,同时执行一个任务
  • 并发
    一个CPU在多个线程间切换,不是真正同时执行多个任务

    线程应用场景

    企业级应用:大量用户进行同时访问,服务器会为每个用户开辟新线程,每个用户操作时就不会相互影响。
    游戏开发:网络通信、图形绘制、运动控制都需要线程单独执行

Java线程的实现

  1. 继承Thread类,重写run方法
    执行线程,调用start方法
    1)定义类继承Thread
    2)重写run方法
    3)创建线程对象,调用start
    面试题:执行start和run有什么区别?
    只有执行start,操作系统才创建新的线程,执行任务,run还是在主线程执行任务,没有新线程,注意:不要手动调用run方法!!

  2. 实现Runnable接口,重写run方法
    1)定义类实现Runnable接口
    2)实现run方法
    3)创建Thread对象,传入Runnable对象
    4)调用start方法

  3. 面试题:继承Thread和实现Runnable哪个好?
    1) 继承Thread类就不能继承其他类,实现Runnable没有此限制
    2)实现Runnable强制要求重写run,继承Thread不要求容易出错

线程的启动和停止

  • 启动必须调用start方法
  • 如何停止?
    1)调用stop方法,执行stop后不会释放锁,可能导致死锁(禁用)
    2)等待run执行完
    3)在run中加入条件,终止run的执行

线程的执行过程

多线程的执行是抢占式的,每个线程可能在执行中间,就被其他线程抢占CPU执行,线程会来回抢占CPU。

线程的优先级

可以控制CPU给线程分配时间片的概率
线程的方法:
setPriority(int priority)
优先级从低到高1~10,默认是5
开发过程中给任务重要的线程分配更高优先级,让该线程优先完成

线程的生命周期

类似人的生老病死,线程也有自己的生命周期

  1. 新建
    创建了线程对象,没有调用start方法
  2. 准备
    线程调用了start方法,CPU还没有分配时间片
  3. 运行
    线程获得时间片,正在执行run方法
  4. 阻塞
    进入阻塞的情况:
    1. 进行IO操作
    2. 进入睡眠 sleep
    3. 进入挂起 suspend
    4. 进入等待 wait
    从阻塞状态恢复:
    1. IO操作完毕
    2. 睡眠时间结束
    3. 执行恢复 resume
    4. 被通知 notify
  5. 死亡
    run执行完毕

技术图片

使用多线程实现聊天程序

单线程中IO会产生阻塞,读写不能同时执行,读写操作必须分别放到不同线程中才能同时执行。

技术图片

线程的睡眠
可以让当前线程进入睡眠状态
Thread.sleep(毫秒数)

后台线程
也叫守护线程(精灵线程)
一种特殊的线程,为其他线程提供服务,一旦其他线程都死亡了,守护线程会自动死亡。一个典型的守护线程就是GC(垃圾收集器)
方法:
setDaemon(boolean b) true 守护线程,false 非守护线程 (默认)
必须在start之前调用

线程的合并
一个线程可以在执行时合并另一个线程,让另一个线程完成执行完,自己再执行。
run(){
另一个线程.join()
}
注意:两个线程之间不能相互合并,否则可能出现死锁情况

作业:

  1. 完成聊天案例
  2. 设计两个线程,一个线程负责求出1~100以内所有的偶数;然后,另外一个线程负责打印1~100以内所有的奇数。
    测试时,分别设置线程的优先级,观察执行的顺序。
  3. 同时启动2个线程,一个用于扫描某个目录下的所有文本文件(包括:java、txt、html),并将文字内容打印出来,一个收集磁盘上所有的图片文件复制到C:images目录下。
  4. 某人正在看电视连续剧,从第1~88集,看到第10集时,来了一个送快递的,收完快递后后,继续看电视。(线程的合并,join)
  5. 多线程模拟龟兔赛跑:
    乌龟和兔子进行1000米赛跑,兔子前进5米,乌龟只能前进1米。
    但兔子每20米要休息500毫秒,而乌龟是每100米休息500毫秒。
    谁先到终点就结束程序,并显示获胜方

以上是关于多线程的主要内容,如果未能解决你的问题,请参考以下文章

线程学习知识点总结

多个请求是多线程吗

python小白学习记录 多线程爬取ts片段

多线程编程

多线程编程

python多线程