并发编程之美

并发编程线程基础
线程
线程是进程中的一个实体,线程本身是不会独立存在的。
进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程则是进程的一个执行路径,一个进程至少有一个线程,进程中的多个线程共享进程的资源。
真正要占用CPU运行的是线程,所以也说线程是CPU分配的基本单位
main()函数时其实就启动了一个JVM进程,而main()函数所在的线程就是这个进程中的一个线程,也称主线程。
一个进程中有多个线程,多个线程共享进程的堆和方法区资源,但是每个线程有自己的程序计数器和栈区域。
程序计数器就是为了记录该线程让出CPU时的执行地址的,待再次分配到时间片时线程就可以从自己私有的计数器指定地址继续执行。
每个线程都有自己的栈资源,用于存储该线程的局部变量,栈还用来存放线程的调用栈帧
堆是一个进程中最大的一块内存,堆是被进程的所有线程共享的,堆里面主要存放使用new操作创建的对象实例。
方法区则用来存放JVM类加载的类、常量及静态变量等信息,也是线程共享的。

线程的创建与运行

三种线程创建方式,分别是实现Runnable接口的run方法,继承Thread类并重写run的方法,使用FutureTask方式
继承Thread类并重写run方法
在这里插入图片描述

使用继承方式的好处是,在run()方法内获取当前线程直接使用this就可以了,无需使用Thread.currentThread()方法,不好的地方是Java 不支持多继承,如果继承了Thread类,那么就不能继承其他类。另外任务没有与代码分离,当多个线程执行一样的任务是时需要多份任务代码,而Runnable没有这个限制。
在这里插入图片描述
如上面所示,两个线程共用一个test代码逻辑,RunnableTest可以继承其他类。但是上面两种方式都有一个缺点,就是任务没有返回值
在这里插入图片描述
CallerTask类实现了Callable接口的call()方法。在main()函数内首先创建一个FutureTask对象(构造函数为CallerTask的实例)然后使用创建的FutureTask对象作为任务创建了一个线程并且启动它,最后通过futureTask.get()等待任务执行完毕并返回结果

小结:
使用继承的好处是方便传参,可以在子类里面添加成员变量,通过set方法设置参数或者通过构造函数进行传递,而如果使用了Runnable方式,则只能使用主线程里面被声明为final的变量,不好的地方是java不支持多继承,如果继承了Thread类,那么子类不能再继承其他类,而Runable则没有这个限制。前两种方式没有办法拿到任务的返回结果,但是FutureTask方式可以。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值