多线程

多线程

一、线程与进程

进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间。
线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行. 一个进程最少有一个线程。
线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分成若干个线程。

二、多线程

同步与异步
同步:排队执行,效率低但是安全
异步:同时执行,效率高但是数据不安全
并发与并行
并发:指两个或多个事件在同一时间段内发生
并行:指两个或多个事件在同一个时刻发生(同时发生)
1.Thread
在这里插入图片描述
这个类是java所提供的用于实现线程的类,我们需要开启一个新的执行路径,我们需要继承Thread。

2.run方法
在这里插入图片描述 run方法就是线程要执行的任务方法,这个方法里面编写的代码就是这个线程要执行的任务,就是一条新的执行路径
这个执行路径的触发方式,不是调用run()方法,而是通过Thread对象的start()方法来启动任务
我们创建一个对象之后,从父类Thread继承start()方法,调用start()方法之后就会启动一个线程,然后在这个线程里面运行run()方法.
不需要调用run()方法,调用的是start()方法
在这里插入图片描述
3.Runnable接口*
在这里插入图片描述
在这里插入图片描述
实现Runnable与继承Thread相比有如下优势:
(1)过创建任务,然后给线程分配的方式来实现多线程。 更适合多个线程同时执行相同任务的情况。
(2)可以避免单继承带来的局限性。
(3)与线程本身是分离的,提高了程序的健壮性。
(4)后续学习线程池技术,接受Runnable类型的任务,不接受Thread类型的线程。

4.通过匿名内部类的方式来实现线程的方式
在这里插入图片描述

5.获取线程的名称
在这里插入图片描述
在这里插入图片描述
6.线程的休眠 sleep
sleep是Thread的一个静态方法,直接用Thread.调用即可。Thread.sleep(1000); 指定休眠时间
在这里插入图片描述
7.线程阻塞
所有消耗时间的操作都可以叫做线程阻塞。
比如说,常见的文件读取,文件读取需要消耗时间。还有等待用户输入,用户不输入,代码就不会往下执行。
总的来说,线程阻塞就是耗时操作。

8.线程中断
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
综上所述,让一个线程中断/死亡的方法就是:用该线程对象调用.interrupt()方法,然后在该线程所在run方法的catch块中添加return;即可。

9.用户线程和守护线
用户线程:当一个进程不包含任何存活的用户线程时,进程结束。
守护线程:守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡。
所以,让一个线程中断/死亡除了上述方法之外,还有一种方法就是把该线程从用户线程变成守护线程。
把用户线程变成守护线程的方法在这里插入图片描述
10.线程不安全问题**
解决方案1,同步代码块
格式:synchronized(锁对象){} ,小括号里边需要传参:锁对象
在这里插入图片描述
案例:在这里插入图片描述
解决方案2,同步方法
格式:在方法中加synchronized修饰,
在这里插入图片描述
案列:在这里插入图片描述
在这里插入图片描述
解决方案3,显式锁Lock 子类ReentrantLock
格式: 显式锁l对象 private Lock l = new ReentrantLock(); 结束时再调用l.unlock()
在这里插入图片描述
11.多线程通信问题:生产者与消费者问题
生产者工作时,消费者在休息,生产者工作结束把消费者唤醒,生产者去休息,消费者工作完把生产者唤醒,消费者去休息。在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
12.带返回值的线程Callable
在这里插入图片描述
在这里插入图片描述

三、线程池

创建线程
创建任务
执行任务
关闭线程

1.缓存线程池
(长度无限制)
任务加入后的执行流程:
(1)判断线程池是否存在空闲线程
(2)在则使用
(3)不存在,则创建线程 并放入线程池,然后使用

第一步:创建缓存线程池在这里插入图片描述
第二部:创建任务,并加入到线程池中
在这里插入图片描述

案例:在这里插入图片描述
2.定长线程池
(长度是指定的数据)
任务加入后的执行流程:
(1判断线程池是否存在空闲线程
(2存在则使用
(3)不存在空闲线程,且线程池未满的情况下,创建线程 并放入到线程池,然后使用
(4)存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程。

第一步:创建定长线程池,并设置长度
在这里插入图片描述
第二步:创建任务,并加入到线程池中在这里插入图片描述
案例:在这里插入图片描述
3.单线程线程池
池里面只有一个线程)
执行流程:
(1)判断线程池的那个线程是否空闲
(2)闲则使用
(3)不空闲 则等待池中的单个线程空闲后 使用

第一步:创建单线程线程池
在这里插入图片描述
第二步:创建一个任务 并把它放到线程池中
在这里插入图片描述
案列:在这里插入图片描述
4.周期任务 定长线程池
执行流程:
1.判断线程池是否为空闲线程
2.空闲则使用
3.不存在空闲线程,且线程池未满情况下 创建线程 并放入池中,然后使用
4.不存在空闲线程,且线程池已满的情况下,等待线程池出现空闲线程

周期性任务执行时:
定时执行,当某个时刻触发时,自动执行某任务

第一步:创建周期定长线程池
在这里插入图片描述
第二步:(第一种情况)

  1. 定时执行一次
    service.schedule(定时执行的任务, 时长数字, 时长数字的单位 TimeUnit.指定)
    参数1:定时执行的任务
    参数2:时长数字
    参数3:时长数字的单位 TimeUnit.指定
    在这里插入图片描述
    第二步:(第二种情况)
    2.周期性执行任务
    (根据某个周期,一直固定执行。/每间隔一定周期去执行任务)
    service.scheduleAtFixedRate(任务,延长时长数字,周期时长数字,时长数字的单位);
    参数1:任务
    参数2:延长时长数字 (第一次执行在什么时间以后)
    参数3:周期时长数字 (第一次执行之后,每隔多久执行一次)
    参数4:时长数字的单位
    在这里插入图片描述

四、Lambda表达式

案例1:在这里插入图片描述
案例2:在这里插入图片描述
在这里插入图片描述

由这两个案列可以看出来Lambda表达式只是把线程任务用 ->代替了,而方法里的其他参数要照写;如果方法无参,那么只用写->即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值