多线程概述

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:一、多线程技术概述 1.线程 2.进程 二、多线程调度方法 1.继承Thread方法 2.实现Runnable接口 3.实现Callable接口 三、

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

本博客介绍了多线程的相关内容,其中包括有多线程的创立,线程池,线程安全性等。


提示:以下是本篇文章正文内容,下面案例可供参考

一、多线程技术概述

     1.线程与进程:
     线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个线程。
     进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间。
   2.  线程调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
     抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么就会随机选择一个。
     CPU使用抢占式调度模式在多个线程间进行告诉切换,对于CPU的一个核心而言,某个时刻只能执行一个线程,而CPU的多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。其实多线程并不能提高程序运行速度,但能提高程序运行效率,让CPU的使用率更高。
     3.同步与异步:
     同步:排队执行,效率低但是安全。
    异步:同时执行,效率高但是数据不安全。
   4.并发与并行:
      并发:两个或多个在同一个时间段内发生。
      并行:~在同一时刻发生。
     二、线程的五种基本状态

在这里插入图片描述

      1.新建状态(new):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();
      2.Runnable:执行中的线程,当调用线程对象的start()方法。
      3.Waiting:无限等待。
      4.Time Waiting:计时等待。
      5.Terminated:被终止了。

二、多线程的创建与启动

一:继承Thread类,重写该类的run()方法。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Thread类的方法与构造方法

Thread(),:创建一个没有任务的线程
Thread(Runnable target):给一个runnable的任务
Thread(name):给任务一个名字
Thread(Runnable target,String name);:通过get name来获取名称
普通方法和一些静态的方法:
getId():返回线程的标识符
GetPriority():返回线程的优先级
SetPriority():优先级
Static int Max_PRIORITY:线程可以拥有最大的优先级
Static int MIN_PRIORITY:最低优先级

总结:

1编写一个类,继承thread,重写run方法。(虽然重写的是run,但是你在main里面调用的是start来启动该线程)
2.重写的run方法就是一条执行路径。
3.子线程里面调用的方法都在子线程里面执行
每个线程都有自己的栈空间,公用一份堆内存。

二、实现Runnable(接口)

    把Runnable传给了Thread。
    
    实现 Runnable与继承Thread相比有什么好处?

1.通过创建任务的方式,然后给线程分配的方式来实现的 多线程,更适合多个线程同时执行相同任务的情况。
2.可哟避免单继承所带来的局限型,因为Java只能单继承,但是允许多实现,还能再继承一个。
3.任务与线程本身分离,提高线程的健壮性;
4.后续的线程池技术,接收Runabble类型任务,不接受Thread类型的线程。
三、

在这里插入图片描述
把Runnable传给了Thread。
实现 Runnable与继承Thread相比有什么好处?
1.通过创建任务的方式,然后给线程分配的方式来实现的 多线程,更适合多个线程同时执行相同任务的情况。
2.可哟避免单继承所带来的局限型,因为Java只能单继承,但是允许多实现,还能再继承一个。
3.任务与线程本身分离,提高线程的健壮性;
4.后续的线程池技术,接收Runabble类型任务,不接受Thread类型的线程。

三、带返回值的线程Callable

可以等多个线程给你返回值
在这里插入图片描述
1.实现类
2.创建任务对象,传入上面编写的Callable对象
3.用方法:get():需要等待计算完成,然后检索结果
4.Get(long timeOUt,timeUnit):等待多少秒,如果超时,就不要了
在这里插入图片描述

三、线程安全

一、同步代码块:synchronized

在这里插入图片描述
()里面要传参,传的是锁的对象
注意:多个线程要看同一把锁(即锁对象相同)才能排序
例子:
首先把这一段if语句作为代码块
在这里插入图片描述
新建一个对象了一个对象
他的属性也只有一个,三个线程在执行任务的时候看的是同一个对象,o

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、同步方法:

方法2,就是同步方法,以方法为单位:就是把synchronized修饰到方法里,
先把要锁的东西抽出来
在这里插入图片描述
变成方法:
在这里插入图片描述
因为要与while循环嵌套,而且不能死循环,所以改成boolean类型的返回值,retrun true和flase
然后在之前循环的地方调用方法:
在这里插入图片描述
当然,也要修改一点点,就是如果是falese(没票了),就结束循环
那么锁的位置加在哪呢?
既然是锁方法,那肯定是加在方法那里啦
在这里插入图片描述
这个的锁是this,如果是静态修饰,那么锁就不是this,是类名.Class
在这里插入图片描述

三、显式锁Lock

子类 ReentranLock
之前的两个方法都是隐式锁
这个是给任务一把锁
在这里插入图片描述
然后在执行语句前锁
在这里插入图片描述
之后在执行完毕后放开在这里插入图片描述

四:公平锁和非公平锁

公平锁:先来先到
不公平锁:一块抢
我们刚刚学的三种方式都是不公平锁,如何实现公平锁呢?
就刚刚显式锁那里:
在这里插入图片描述
传入一个True,就是公平锁啦
<font color=#999AA
五:多线程通信问题:
生产者与消费者的问题:厨师没把菜做完,服务员不能端走菜,就是厨师做菜时,服务员休息。服务员端菜时,厨师休息。就是两个线程用同一个对象,确保安全
Objcet类里的几个方法:
Wait(long timeoutMillis)):等待直到被唤醒,或到一定时间
要统一对象,就比如说a线程通过对象haha()睡着了,那其他线程想要唤醒a线程就要调用haha()的唤醒
Notify():随机唤醒一个
NotifyALL():唤醒等待此对象监视器的所有线程

四、线程池:

线程池:以后开发中,经常不可避免写很多线程,而线程有些很多,用了一次就消失的。
在这里插入图片描述

正常来说线程是这样的,其实真正花时间的是创建线程和关闭线程,中间那两个一下子就执行了的。那么如果有很多这种线程的话就浪费大量的时间,降低系统效率,所以用线程池:可以省去大量创建和关闭线程的时间。
线程池分四种:

一、缓存线程池:(长度无限制):

创建一个缓存的线程池
在这里插入图片描述
有空位就会让线程上,而不是新打印一个线程
在这里插入图片描述

二、定长线程池 :

在这里插入图片描述
后面的FixedThreadPool:就是固定线程池
由于是固定长度的,所以我们需要给一个长度
在这里插入图片描述

三、单线程线程池:用在子线程排队

在这里插入图片描述

四、周期性任务定长线程池

在这里插入图片描述
然后里面的2是长度,返回类型不一样,执行方法也不一样,有两个方法。
参数有三个:
1是定时执行的任务:在这里插入图片描述
2是时长数字:在这里插入图片描述

3是时长数字的单位,TimeUnit的常量指定在这里插入图片描述
周期执行的任务:
参数1:任务

在这里插入图片描述
参数2:延迟时长数字:在这里插入图片描述
参数:周期时长数字:(每隔多久执行一次)
在这里插入图片描述
参数4:时长数字的单位()在这里插入图片描述

五、Labbda表达式

Lambda表达式:是函数式编程思想,跟面向对象不同,面向对象是创建对象调用方法,解决问题。
函数式重点是方法:不关注过程,只注重结果。
例子:首先写一段冗余的Runnable代码:
在这里插入图片描述

看,为了输出一段字,而需要这么多的代码,现在来看太长了,我们可以用匿名的方式。
在这里插入图片描述
在这里插入图片描述
重点关注是new对象,
所以出现了Lambda表达式:在这里插入图片描述
对比发现代码量变少了,这里用的是runnable,runable使用的时候在声明这个方法不需要参数,
如果用的是其他接口,需要传参数,那么在()写入参数即可,如果有返回值的话,则在{}里写返回值即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值