结合多本著作和个人开发经验,整理Java多线程入门手册

前段时间推出的Java8新特性文章收到大家广泛关注和好评,非常感谢各位支持,这段时间苦思冥想,决定输出一波Java多线程技能点,希望可以在大家的工作和面试中有所帮助!本篇文章为多线程系列第一章,主要讲解一下几点:,多线程好处和应用场景,多线程的相关概念和术语,Java线程创建方式,Thread类详解,线程的常用方法,线程5种状态和6种状态,两种版本解释,线程状态之间转换,Java设计者写过一个很有影响力的白皮书,用来解释设计的初衷,并发布了一个简短的摘要,分为11个术语:,其中多线程就是本次要接触的,白皮书中对多线程的解释:,多线程可以带来更好的交互响应和实时行为。,如今,我们非常关注并发性,因为摩尔定律行将完结。我们不再追求更快的处理器,而是着眼于获得更多的处理器,而且要让它们一直保持工作。不过,可以看到,大多数编程语言对于这个问题并没有显示出足够的重视。Java在当时很超前。它是第一个支持并发程序设计的主流语言。从白皮书中可以看到,它的出发点稍有些不同。当时,多核处理器还很神秘,而Web编程才刚刚起步,处理器要花很长时间等待服务器响应,需要并发程序设计来确保用户界面不会”冻住”。并发程序设计绝非易事,不过Java在这方面表现很出色,可以很好地管理这个工作。,在操作系统中有多任务【multitasking】,在同一刻运行多个程序【应用】的能力。例如,在听音乐的同时可以边打游戏,边写代码。如今我们的电脑大多都是多核CPU,但是,并发执行的进程【正在执行的应用】数目并不是由CPU数目制约的。操作系统将CPU的时间片分配给每一个进程,给人并行处理的感觉。,程序【program】:为了完成特定任务,用某种语言编写的一组指令的集合。程序就是一堆代码,一组数据和指令集,是一个静态的概念。就说我们程序员写的那玩意。比如:安装在电脑或者手机上的各种软件,今日头条、抖音、懂车帝等,如果一个程序支持多线程,这个程序就是一个多线程程序,进程【Process】:是程序的一次执行过程或者说是正在运行的程序,是一个动态概念,进程存在生命周期,也就是说程序随着程序的终止而销毁,线程【Thread】:线程是进程中的实际运作的单位,是进程的一条流水线,是程序的实际执行者,是最小的执行单位。通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程。线程是CPU调度和执行的最小单位,CPU时间片:时间片即CPU分配给各个程序的时间,每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的,如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。而不会造成CPU资源浪费,并行【parallel】:多个任务同时进行,并行必须有多核才能实现,否则只能是并发,比如:多名学生有问题,同时有多名老师可以辅导解决,串行【serial】:一个程序处理完当前进程,按照顺序接着处理下一个进程,一个接着一个进行,比如:多名学生有问题,只有一名老师,需要挨个解决,并发【concurrency】:同一个对象被多个线程同时操作。(这是一种假并行。即一个CPU的情况下,在同一个时间点,CPU只能执行一个代码,因为切换的很快,所以就有同时执行的错觉),比如:多名学生有问题,只有一个老师,他一会处理A同学,一会处理B同学,一会处理C同学,频繁切换,看起来好似在同时处理学生问题,实际应用中,多线程非常有用,例如,QQ音乐就是一个多线程程序,我们可以一边听音乐,一般下载音乐,还可以同时播放MV等非常方便。一个Web服务器通过多线程同时处理多个请求,比如Tomcat就是多线程的。,注意:程序会因为引入多线程而变的复杂,多线程同时会带来一些问题,需要我们解决,多线程多数在浏览器、Web服务器、数据库、各种专用服务器【如游戏服务器】、分布式计算等场景出现。,在使用Java编写后台服务时,如果遇到并发较高、需要后台任务、需要长时间处理大数据等情况都可以创建线程单独的线程处理这些事项,多线程的目的就在于提高处理速度,减少用户等待时间,线程创建有4种方式:,方式1:继承Thread类,方式2:实现Runnable接口,方式3:实现Callable接口,方式4:使用线程池【这块后边单独说,它更像是管理线程的手段】,步骤:,JDK源码中,Thread类定义实现了Runnable接口,结合多本著作和个人开发经验,整理Java多线程入门手册,所以知道重写的run方法从哪来的了吧!就是从Runnable接口中来的,需求:创建线程计算10以内的偶数,线程类:,测试类:,测试类中输出了一句话:主线程,打印结果:,结合多本著作和个人开发经验,整理Java多线程入门手册,步骤:,同样的需求打印10以内的偶数,实现类:,测试类:,FutureTask类:,结合多本著作和个人开发经验,整理Java多线程入门手册,RunnableFuture接口:,结合多本著作和个人开发经验,整理Java多线程入门手册,步骤:,案例:还是计算10以内的偶数,这一次将计算结果返回,因为有多个数据所以返回数据用集合存储,则Callable接口的泛型类型应该是集合,实现类:,测试类:,结合多本著作和个人开发经验,整理Java多线程入门手册,线程的状态网上有 5种状态 和 6种状态 两个版本,五种状态版本:是基于现代操作系统线程状态角度解释的,新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态,就绪:处于新建状态的线程被start后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源,运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能,阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时终止自己的执行,进入阻塞状态,死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束,在JDK5的时候Thread类中定义了一个State枚举类,其中定义了6种线程状态,这是Java官方定义的Java线程的6种状态,结合多本著作和个人开发经验,整理Java多线程入门手册,1)NEW:处于NEW状态的线程此时尚未启动。只是通过new Thread()创建了线程对象,并未调用start()方法,2)RUNNABLE:Java线程的 RUNNABLE 状态其实是包括了传统操作系统线程的 就绪(ready) 和 运行(running) 两个状态的。处于 RUNNABLE 状态的线程可能在 Java 虚拟机中运行,也有可能在等待 CPU 分配资源,3)BLOCKED:阻塞状态。处于 BLOCKED 状态的线程正等待锁的释放以进入同步区,就好比你去食堂打饭,只有一个窗口你就得排队,等前边的人结束之后你完成打饭,4)WAITING :等待状态。处于等待状态的线程变成 RUNNABLE 状态需要其他线程唤醒,可以通过调用一下三个方法进入等待状态:,5)TIMED_WAITING:超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。,调用如下方法会使线程进入超时等待状态:,6)TERMINATED:终止状态。此时线程已执行完毕。,其实等待和锁定状态可以被笼统的称为阻塞状态,就是停着不动了嘛,在回答面试题时建议回答6种状态版本,就是是JDK源码中定义的,一来有官方支持,二来证明咱看过一点源码。,线程之间的状态转换可以参考下图,结合多本著作和个人开发经验,整理Java多线程入门手册,从源码看出Thread类一共有9个构造方法,除第三个为default修饰【同包可用】,其他都是public,结合多本著作和个人开发经验,整理Java多线程入门手册,实现类:,测试类:,运行结果:,结合多本著作和个人开发经验,整理Java多线程入门手册,或者通过setName()方法设置线程名,如果不设置线程名,默认为【”Thread-” + nextThreadNum()】,nextThreadNum方法使用 threadInitNumber静态变量,默认从0开始,每次+1,结合多本著作和个人开发经验,整理Java多线程入门手册,不设置线程名运行效果如下,结合多本著作和个人开发经验,整理Java多线程入门手册,sleep方法可以让线程阻塞指定的毫秒数。时间到了后,线程进入就绪状态。sleep可用来研模拟网络延时,倒计时等。每一个对象都有一个锁,sleep不会释放锁,锁的概念后边会详细讲解,实现类:,测试类:,运行结果:,结合多本著作和个人开发经验,整理Java多线程入门手册,”善用”sleep年入百万不是梦:,结合多本著作和个人开发经验,整理Java多线程入门手册,提出申请释放CPU资源,至于能否成功释放取决于JVM决定,调用yield()方法后,线程仍然处于RUNNABLE状态,线程不会进入阻塞状态,保留了随时被调用的权利,实现类:,测试类:,运行结果:,第五次执行是线程2执行开始结束后输出的线程1开始结束,这就说明CPU并没有切换到别的线程,说明并没有释放CPU资源,结合多本著作和个人开发经验,整理Java多线程入门手册,将当前的线程挂起,当前线程阻塞,待其他的线程执行完毕,当前线程才能执行,可以把join()方法理解为插队,谁插到前面,谁先执行,在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将可能早于子线程结束。如果主线程需要知道子线程的执行结果时,就需要等待子线程执行结束了。主线程可以sleep(xx),但这样的xx时间不好确定,因为子线程的执行时间不确定,join()方法比较合适这个场景,运行结果:,结合多本著作和个人开发经验,整理Java多线程入门手册,改变、获取线程的优先级。Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。线程的优先级用数据表示,范围1~10。线程的优先级高只是表示他的权重大,获取CPU执行权的几率大。先设置线程的优先级,在执行start()方法,JDK提供的【stop()、destroy()】两种方法已废弃,不推荐再使用。推荐线程自动停止下来,就比如上边的所有案例,都是执行完了run方法中的所有代码之后线程就自然结束了。如果线程需要循环执行,建议使用一个标识位变量进行终止,当flag=false时,则终止线程运行,比如:定义一个名为【线程1】的子线程,当主线程执行3次循环之后,线程1停止运行,实现类:,测试类:,文章出自:​​石添的编程哲学​​,如有转载本文请联系【石添的编程哲学】今日头条号。

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/19695.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34