Java线程-小记03

线程相关的基本概念

线程:一般在java中,我们指一个事务的动态执行的过程就是一个线程,线程是操作系统能进行运算调度的最小单位。在线程中,我们将需要执行的方法块放在指定的位置,线程不能独立存在,即使只有一个线程,它也必须依附在一个进程中被执行。

进程:一个进程包含一个或者多个线程,在运行时操作系统会分配给进程内存空间去运行。

小结:线程本身的概念是容易理解的,一般来讲,我们学习java会从最小的部分二进制开始,然后学习数据类型和关键字,再学习到方法,那么在学过接口以后,我们需要明白,java程序在运行中,程序就是由一个或多个线程一步步运行起来的。

线程的执行过程

图1.Java线程的生命周期

 线程的状态根据不同的划分规则分为5种或者6种,这种我用的是6种划分方式,我更加细化了等待状态。首先,整个线程的生命周期如图1所示,图片的来源Life Cycle of Thread in Java | Thread State - Scientech Easyicon-default.png?t=M4ADhttps://www.scientecheasy.com/2020/08/life-cycle-of-thread-in-java.html/

 根据图片,我们可以划分线程的状态:

NEW:新建状态。指创建了一个线程,启动之前处于该状态。一旦我们用Tread方法去New一个新线程。即使这个线程还没有进行进行任何操作,它已经进入NEW状态。

RUNNABLE:可运行状态。当我们对线程调用run()方法时,线程就进入了这个状态。

BLOKED:阻塞状态。如果该线程运行后没有获得synchronized锁对象,就处于该状态。

WAITING:无线等待状态。获取Lock锁对象失败,就处于该状态。

TIMED_WAITING: 计时等待状态。当线程执行sleep方法时,就会进入这个状态,注意,如果sleep方法的参数是0,则线程会进入WAITING状态。

TERMINATED:消亡状态。线程执行完所有的事物后会进入该状态。

线程只会出现以上6中状态的其中一个,那么一个线程从开始到结束需要如何具体操作。

线程的创建方式

1>通过继承thread类本身。如图2和图3所示

图2.创建一个类继承Thread

 

图3. 调用该类的对象去实现线程

总的过程就是需要继承Tread类,然后重写里面的run方法,在该方法中将需要执行的代码写进去,之后再创建该类的对象(),这样就创建了一个线程。不过这个方法并不推荐,因为在java中,一个子类只能有一个父类,所以局限性很大。因此,我们可以使用 线程相关的接口去实现线程。

2>实现Runnable接口去创建线程。

一个类是可以实现多个接口,“创建线程”对于一个类来所只是一个功能。我们先看Runnable接口的底层代码。

 图4.Runable接口的底层代码

这个接口是函数式接口(函数式接口指该接口有且只有一个抽象方法),我们知道接口是必须要重写抽象方法的,同时接口还能使用匿名内部类的方式去写,如图5,我们不需要再用继承的方式

 

 

图5.Runnbale接口实现线程

先创建接口的实现类,然后调用thread的有参构造函数,参数类型就是runnable接口的实现类,这样就可以建立一个线程。这种方式还可以用lamda表达式去进一步省略如图6。

 

 图6. lamda省略写法建立线程

3>通过Callable接口去创建线程

Callable也是一个带泛型的函数接口,call方法的返回值就是泛型。

图7. Callable接口的底层代码

如果用Callable接口的实现类想创建线程,不能用Thread类的有参构造去建立,因为没有Callable实现类的参数,我们需要创建线程池,然后将这个实现类放入线程池中执行。那么接下来,我们需要如何建立一个线程池。

线程池的基本使用

线程池(ThreadPool):通俗易懂的将,线程池就是放线程的池子,里面的线程会按照一定地规则去运行。

线程池的好处:

1.提高响应速度。预先创建好了线程,只等任务过来执行。
2.降低资源消耗。线程池中的线程,执行完任务后,又返回到线程池中,下一个任务到来后可以继续使用该线程。
3.提高线程的可管理性。一个线程大约需要消耗1M的空间,线程池可以设置最大线程的数量。

在线程池中,有可能出现这样一种状况:两个线程同时执行,这时就会出现两种不同的情况。

并发:在某个时间段内,多个程序都处在执行和执行完毕之间;但在一个时间点上只有一个程序在运行。

并行:在某个时间段里,每个程序按照自己独立异步的速度执行,程序之间互不干扰。

由上面两个概念可以知道,线程池是需要限制线程的个数去对线程进行管理,这样防止CPU突然同时处理大量的线程。

接下来,我们创建一个最简单的线程池并且使用Callable接口创建线程如图8。

图8. 用线程池实现Callable接口

线程的通信

 概念:多个线程在处理同一个资源,但是处理的动作去不相同。

如果不对线程上锁,那么当多个线程处理同一个资源时,可能会造成数据的损失或者结果不是我们想要的结果。比如有个包子,人只有包子数等于1时才能吃包子,包子铺只有包子数量等于0时才生产包子。如果包子的数量刚变成1,这个线程还没结束,人就开始吃包子,那么这个逻辑就是不对的。

这里我们需要知道Object类中的一些方法:

wait() :让线程进入等待状态,不再去抢“锁",只有被通知(notify)时,才会进入线程的调度队列。

notify(): 让选取的对象线程从"锁"的状态被释放,可以被cpu调用。

notifyall(): 整个wait set的全被线程被释放且能被cpu调用。

 

 从以上一些列代码中,我们可以看到包子铺和吃货有个共有的资源:包子。通过object的方法可以保证包子铺生成包子完后吃货才会吃包子。这才是我们想要的逻辑。

线程

以上内容只是线程的冰山一角,线程在java的学习中会从基础贯穿到架构,合理地建立线程,可以让程序功能更全的同时,占用的内存也很少。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值