Java并发编程(01):线程的创建方式,状态周期管理
一、并发编程简介
1、基础概念
- 程序
与计算机系统操作有关的计算机程序、规程、规则,以及可能有的文件、文档及数据。
- 进程
进程是计算机中的程序,关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
- 线程
线程是操作系统能够进行运算调度的最小单位,包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
- 顺序编程
程序中的所有步骤在任意时刻只能执行一个步骤。编程中绝大部分场景都是基于顺序编程。
- 并发编程
在一台处理器上“同时”处理多个任务,并行处理程序中的复杂耗时任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生。
2、入门案例
public class HelloThread { public static void main(String[] args) { System.out.println("Hello,Thread"); // 当前线程名称 System.out.println(Thread.currentThread().getName()); // 线程系统的管理接口 ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long[] threadIds = threadMXBean.getAllThreadIds() ; for (long id : threadIds) { ThreadInfo threadInfo = threadMXBean.getThreadInfo(id) ; System.out.println(threadInfo.getThreadId()+ ":"+threadInfo.getThreadName()); } } }
打印结果:
5:Monitor Ctrl-Break 4:Signal Dispatcher 3:Finalizer 2:Reference Handler 1:main
由此可知上述一段简单的Java程序,不止一条main线程在执行。
二、线程创建方式
1、继承Thread类
Thread类的基础结构:
class Thread implements Runnable
这里已经实现了Runnable接口。
public class CreateThread01 { public static void main(String[] args) { // 调用方法 MyThread1 myThread1 = new MyThread1() ; myThread1.start(); } } class MyThread1 extends Thread { // 设置线程名称 public MyThread1 (){ super("CicadaThread"); } @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
2、实现Runnable接口
如果创建的线程类已经存在父类,则不能再继承Thread类,在Java中不允许多继承,这时就可以实现Runnable接口。
public class CreateThread02 { public static void main(String[] args) { Thread thread = new Thread(new MyThread2(),"MyThread2") ; thread.start(); } } class MyThread2 implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()+" run ..."); } }
3、匿名内部类
在一个类里面定义一个类,称为内部类。内部类就相当于外部类的一个成员,可以把内部类看成一个整体。
public class CreateThread03 { public static void main(String[] args) { //方式1 new Thread("ThreadName1") { public void run() { System.out.println("1:"+Thread.currentThread().getName()); }; }.start(); //方式2 new Thread(new Runnable() { public void run() { System.out.println("2:"+Thread.currentThread().getName()); } },"ThreadName2"){ // 这里重写了run方法 @Override public void run() { System.out.println("3:"+Thread.currentThread().getName()); } }.start(); } }
4、返回值线程
顾名思义,该线程线程异步执行后,可以返回线程的处理结果。
public class CreateThread04 { public static void main(String[] args) throws Exception { MyThread4 myThread4 = new MyThread4(); FutureTask<Integer> task = new FutureTask<>(myThread4); Thread thread = new Thread(task,"TaskThread"); thread.start(); // 等待获取结果 // Integer result = task.get(); // 设置获取结果的等待时间,超时抛出:TimeoutException Integer result = task.get(3, TimeUnit.SECONDS) ; System.out.println("result="+result); } } class MyThread4 implements Callable<Integer> { // 封装线程执行的任务 @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName()); Thread.sleep(1000); return 2+3; } }
5、定时任务
Timer是后台线程执行任务调度的工具类,可以根据规则配置定期执行或者重复执行。
class TimerTask implements Runnable
任务类:TimerTask结构实现Runnable接口。
public class CreateThread05 { public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("延迟1s,每隔3s执行一次"); } }, 1000, 3000); } }
6、线程池管理
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。
public class CreateThread06 { public static void main(String[] args) { Executor threadPool = Executors.newFixedThreadPool(5); for(int i = 0 ;i < 5 ; i++) { threadPool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }); } } }
三、线程状态管理
1、状态描述
- NEW
初始状态:构建线程实例后,调用start()方法启动前,处于该状态。
- RUNNABLE
运行状态:在Java线程中,就绪和运行两个状态称作运行状态,在实际的执行过程中,这两个状态是随时可能切换的。启动start()方法被调用,或者sleep()后,join()结束等,就进入RUNNABLE就绪状态,开始等待CPU时间片;线程调度选中该线程、并分配了CPU时间片后,该线程尽管处于Runnable状态,就是运行状态(Running);
- BLOCKED
阻塞状态:通常指被锁机制阻塞,表示线程正在获取有锁控制的资源。
- WAITING
等待状态:进入该状态的线程,等待被其他线程发出通知或中断,也称显式唤醒。
- TIMED_WAITING
超时等待状态:该状态不同于WAITING状态,该状态的线程可以在指定的时间后自动唤醒;
- TERMINATED
终止状态:表示当前线程任务执行完毕。
2、案例流程分析
public class StateCycle01 { public static void main(String[] args) throws Exception { // 进入初始状态 StateThread01 stateThread01 = new StateThread01(); FutureTask<String> task = new FutureTask<>(stateThread01); Thread thread = new Thread(task,"GetValueThread"); // 运行状态 thread.start(); // 超时等待结果 String result = task.get(3, TimeUnit.SECONDS) ; System.out.println("result="+result); StateThread02 stateThread02 = new StateThread02() ; Thread thread1 = new Thread(stateThread02,"WaitThread"); thread1.start(); } } class StateThread01 implements Callable<String> { @Override public String call() throws Exception { // 超时等待 Thread.sleep(1000); return "Hello,Cicada"; } } class StateThread02 implements Runnable { @Override public void run() { synchronized (StateCycle01.class) { System.out.println("进入线程..."); try { // 等待状态,放弃对象锁 StateCycle01.class.wait(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程继续..."); } } }
上述流程描述了线程不同状态之间的切换,基本流程图如下。
线程的状态描述起来不算复杂,但是每个状态间的切换,是非常的复杂,后续会分模块单个解释。
四、优缺点总结
1、优点说明
最直接作用使程序执行的效率大幅度提升;程序异步解耦,在web开发中,经常有后续的程序要执行,有需要快速的用户界面响应;当然熟练使用并发编程,也是一个优秀程序员必备技能 。
2、缺点分析
并发编程学习的曲线非常陡峭,难度较大;多线程之间争抢资源容易出现问题;并不是线程越多,执行速度就越快,线程之前切换是耗时的,需要合理创建和使用锁机制;线程创建和之间的通信需要很清晰的逻辑;线程死锁问题更是无法完全避免的问题;所以在一般情况下公司对线程使用的规范是十分严格的。
五、源代码地址
GitHub·地址 https://github.com/cicadasmile/java-base-parent GitEE·地址 https://gitee.com/cicadasmile/java-base-parent
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
2020教你玩转阿里云优惠集锦大汇总 入口链接领取都在这
平台这么多福利折扣优惠你知道吗?除了买产品可以折扣,还有现金奖励,福利红包,抽奖礼品例如突发性能型t5实例1核2G1M云服务器一单下来只要74.43元。这可是官方折扣,下面我们就来整理下阿里云官网的所有优惠锦集赶紧收藏,分享吧 阿里云降本增效一亿补贴,2020上云采购季新年第一大促红包现金奖励你领取了吗? 超级品类日 天天有爆款看日历查运势,抢爆款省到底,看直播涨知识2020年3月5日—2019年3月8日为IoT物联网超级品牌日专场活动,其中包括:3月5日 00:00 – 3月5日 24:00 :IoT物联网平台云产品指定商品折上返券;3月6日 00:00 – 3月6日 24:00 :IoT物联网安全指定商品低至5折起;3月5日 00:00 -3月8日 24:00 : IoT物联网防疫指定商品商品低至7.5折起;3月5日 00:00 -3月8日 24:00 : IoT物联网边缘网关指定商品低至7.6折起。 爆款产品推荐专区 新老用户均可购买,几十款云产品限时特惠,叠加购物车享受满减返利更多优惠在云小站上购买“爆款产品5折起”专区还可以获得老用户15%的返利只要加入云大使即可获得云大使专...
- 下一篇
写代码写了好几年,才发现自己天天都在用设计模式!
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者。 系列文章介绍 本系列文章主要围绕程序员,特别是Java或者后端程序员必须掌握的一些技术和技能,这些文章都是结合我个人的编程学习经历,总结和沉淀下来的方法论。作者目前在阿里做Java,忙里偷闲分享一些技术文章,希望能让更多人更容易地学习编程。 系列文章将会把一些技术学习方法、过程、要领与我的学习经验相结合,更加浅显易懂,并且我也会把我学习时用的资料,书籍和文章拿出来分享给大家,节省你我的时间。所谓授人以鱼也要授人以渔,是本系列文章希望达到的目标。 一个热爱分享的程序员,一个爱生活的斜杠青年。分享程序员编程学习干货和个人成长心得,期待你的关注,让我们一起进步! 本文思维导图 什么是设计模式 学习编程的朋友,想必对于设计模式这个词并不陌生,至少你一定也听说过,如果你是做Java的,那么就更加需要了解设计模式了,为什么这么说呢,因为Java作为一门面向对象语言,很多代码都可以通过设计模式得到简化、规范,提升编码效率和可读性。 按照百度百科的说法,软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Mario游戏-低调大师作品
- 2048小游戏-低调大师作品
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案