今天我们先来聊聊有关线程的话题......

一. 线程概述

1. 简单区分程序、进程和线程

程序是指一段静态的代码

进程是指正在执行的程序,将静态的代码运行起来

线程是指正在执行程序的小单元

举个栗子,班级准备大扫除,在大扫除之前,老师在纸上列了一个清单,每个同学都有不同的工作任务,分配好任务之后,每个同学都是有条不紊地完成自己的任务,扫地的同学去扫地,擦黑板的同学去擦黑板,清理桌子的同学清理桌子......在这个例子里,这个清单就是程序,而这个班级的全体同学是一个整体,也就是一个进程,最后,这个班级里面一个个同学就是一个个线程。

2. 理解进程

理解线程之前,先简单理解一下进程。进程的三大特征:独立性、动态性、并发性。

独立性:指进程是系统中独立存在的实体,拥有独立的资源(eg:私有的地址空间)。

动态性:这是相对于程序而言的,程序是一段静态的代码,而进程是活动的,拥有自己的生命周期。

并发性:多个进程可以在单个处理器上并发执行,互不影响。

还是上面那栗子,这个班级就是一个进程,他是一个整体,他拥有自己的教室,有自己的班级名字,这里可以体现出独立性。这个班级的全体人员按照的任务清单干活,直至把教室打扫干净(即完成任务),这里可以体现出动态性。并发性呢,首先这个班级不只有一个,还有好多其他的班级,他们也可以打扫他们自己的教室,互不影响。

3. 理解线程

线程是进程的执行单元,在程序中,线程是独立的、并发的执行流。

线程的特点:

每个线程有自己的堆栈,自己程序计数器,自己的局部变量,这里体现了线程的独立性。

相同父进程下的所有线程共享进程独立的内存单元(eg:代码段、进程的共有数据),为此可以实现线程间的相互通信。

多个线程之间也可以并发执行,互不影响。

4. 多线程 VS 多进程

线程之间可以共享内存,而进程之间不可以。

系统创建线程代价比较小,而且多线程是实现多任务并发比多进程的效率更高。

Java语言内置了多线程功能,简化了Java多线程编程。

二. 线程的创建和启动

1. 继承Thread类创建线程类

步骤:

定义一个线程类,需继承Thread类。

重写父类的run( )方法,此方法是线程执行体,供cpu自动调用(cpu会用调度策略去处理就绪状态的线程)。

创建线程类的实例对象,调用start( )方法,这个方法告诉cpu这个线程对象进入就绪状态。

1 packagecom.hx.thread;2 ​3 //1.定义一个线程类,需继承Thread类。

4 public class MyThread1 extendsThread {5 //2.重写run方法

6 public voidrun() {7 for (int i = 0; i < 100; i++) {8 System.out.println(Thread.currentThread().getName() + " " +i);9 try{10 Thread.sleep(10);11 } catch(Exception e) {12 e.printStackTrace();13 }14 }15 }16

17 public static void main(String[] args) throwsException {18 //3.创建线程实例,调用start方法,进入就绪状态,交给cpu

19 MyThread1 myThread1 = newMyThread1();20 myThread1.start();21 for (int i = 0; i < 100; i++) {22 System.out.println(Thread.currentThread().getName() + " " +i);23 Thread.sleep(10);24 }25 }26 }

2. 实现Runnable接口创建线程类

步骤:

定义一个线程类,需实现Runnable接口。

实现接口的run( )方法,此方法是线程执行体,供cpu自动调用(cpu会用调度策略去处理就绪状态的线程)。

创建线程类的实例对象。可是Runnable没有start( )方法,因此需要第4步。

创建一个Thread对象(真正的线程对象),用来包装上面的那个实例对象,然后调用start( )方法。

1 packagecom.hx.thread;2 ​3 //1.定义一个线程类,需实现Runnable接口。

4 public class MyThread2 implementsRunnable {5 //2.实现接口的run( )方法

6 @Override7 public voidrun() {8 for (int i = 0; i < 100; i++) {9 System.out.println(Thread.currentThread().getName() + " " +i);10 try{11 Thread.sleep(10);12 } catch(Exception e) {13 e.printStackTrace();14 }15 }16 }17 ​18 public static void main(String[] args) throwsException {19 //3.创建线程类的实例对象

20 MyThread2 myThread2 = newMyThread2();21 //4.创建一个Thread对象(真正的线程对象),用来包装上面的那个实例对象,然后调用start( )方法。

22 Thread t = newThread(myThread2);23 t.start();24 for (int i = 0; i < 100; i++) {25 System.out.println(Thread.currentThread().getName() + " " +i);26 Thread.sleep(10);27 }28 }29 }

3. 实现Callable接口创建线程类

步骤:

定义一个线程类,需实现Callable接口。实现Callable接口的call( )方法,此方法是线程执行体。创建线程类的实例对象。创建FutureTask的对象来包装线程类实例对象。创建Thread的对象来包装Future类的实例对象。

1 packagecom.hx.thread;2 importjava.util.concurrent.Callable;3 importjava.util.concurrent.FutureTask;4 ​5 //1.定义一个线程类,需实现Callable接口

6 public class MyThread3 implementsCallable {7 //2.实现Callable接口的call()方法

8 @Override9 public String call() throwsException {10 for (int i = 0; i < 100; i++) {11 System.out.println(Thread.currentThread().getName() + " " +i);12 Thread.sleep(10);13 }14 returnThread.currentThread().getName();15 }16 ​17 public static void main(String[] args) throwsException {18 //3.创建线程类的实例对象

19 MyThread3 myThread3 = newMyThread3();20 //4.创建FutureTask的实例对象来包装线程类实例对象

21 FutureTask futureTask = newFutureTask(myThread3);22 //5.创建Thread的实例对象来包装Future类的实例对象

23 Thread t = newThread(futureTask);24 t.start();25 for (int i = 0; i < 100; i++) {26 System.out.println(Thread.currentThread().getName() + " " +i);27 Thread.sleep(10);28 }29 //打印出call()方法的返回值

30 System.out.println(futureTask.get());31 }32 }

4. 三种方式的对比

采用继承Thread类这种方式来创建线程,编写简单,可是由于Java不支持多继承,所以不能再继承其他父类。

采用实现Runnable接口或Callable接口,可以继承其他类,多个线程可以共享同一个target对象,非常适合多个线程来处理同一资源的情况,可以更好地体现面向对象的特点,不过编写比较复杂。

采用实现Callable接口,call( )方法是线程执行体,有返回值,可以抛出异常,其功能比run( )方法更强大。

三. 线程的生命周期

四. 控制线程

Thread类的工具方法

join( ):让一个线程等待另外一个线程完成的方法,当在某个程序执行流中调用其他线程的join方法,调用线程将被阻塞,直至join线程完成。

setDaemon(true):指定线程设置为后台线程。在start( )之前调用。后台线程,又称守护线程、精灵线程,其作用是为其他线程提供服务(eg:JVM的垃圾回收线程),如果所有的前台线程都死亡,后台线程也会自动死亡。

sleep( long time):设置线程睡眠时间,参数单位为毫秒,调用此方法线程进入阻塞状态。

setPriority(int newPriority):设置优先级,参数范围:1-10,一般使用三个静态常量(MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY)。

嘻嘻,今天的内容就先到这吧,欢迎大家前来留言。

由于现在个人水平有限,文章若存不当之处,还请各位大佬们加以斧正。

java 线程的理解_浅谈对多线程的理解(一)相关推荐

  1. java中virtual关键字_浅谈virtual、abstract方法和静态方法、静态变量理解

    说点对这几个容易混淆的词的理解: 1.c++中的virtual方法的 virtual关键字主要是防止继承中重复继承父类的同一个方法而设置的标识. 2.virtual与abstract关键字的不同之处在 ...

  2. java变量命名规则_浅谈JAVA开发规范与开发细节(上)

    开发团队在开发过程中,由于每个人的开发习惯,以及对于技术的理解深浅程度不一,往往一个项目在开发过程中,代码的质量,代码的风格都不尽相似,所以有一份适合团队的代码规范是非常有必要的,而一个团队的代码规范 ...

  3. java内存模型浅析_浅谈java内存模型

    不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的.其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改.总结jav ...

  4. java 定时任务怎么关闭_浅谈springboot项目中定时任务如何优雅退出

    在一个springboot项目中需要跑定时任务处理批数据时,突然有个Kill命令或者一个Ctrl+C的命令,此时我们需要当批数据处理完毕后才允许定时任务关闭,也就是当定时任务结束时才允许Kill命令生 ...

  5. java 中的排序_浅谈java中常见的排序

    浅谈java中常见的排序 学过java的人都知道,排序这一部分初次接触感觉还是有点难以理解,很多地方也会用到.然而,在java中常见的排序方法:冒泡排序,选择排序,插入排序等等.下面就让我们一起揭开他 ...

  6. java 中的单元测试_浅谈Java 中的单元测试

    单元测试编写 Junit 单元测试框架 对于Java语言而言,其单元测试框架,有Junit和TestNG这两种, 下面是一个典型的JUnit测试类的结构 package com.example.dem ...

  7. java编程double相乘_浅谈Java double 相乘的结果偏差小问题

    看下面的一段代码的运行结果: public class TestDouble { public static void main(String[] args) { double d =538.8; S ...

  8. java dao service实例_浅谈Action+Service +Dao 功能

    1. Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. D ...

  9. java布尔类型比较器_浅谈Java中几种常见的比较器的实现方法

    在java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题. 通常对象之间的比较可以从两个方面去看: 第一个方面:对象的地址是否一样,也就是是否引用自同一个对象.这种方式可以直接使用& ...

最新文章

  1. 2021 年度热门技术书单提前公开,这些好书藏不住了
  2. 寿光农商行计算机机房,寿光农商银行 举办2021年新员工入职仪式
  3. 设计模式-结构性模式
  4. 【技术综述】一文道尽softmax loss及其变种
  5. Echarts使用笔记
  6. Docker安装Logstash7.7.0
  7. rhel 6下配置网络yum源(虚拟机环境下)
  8. java系统时间怎么获取,java目前系统时间的获取
  9. ajax调用后台java类_ajax调用java后台方法是什么
  10. java 递归深度优先遍历_Java基础 - 二叉树的遍历之深度优先遍历(递归遍历)
  11. Hinton神经网络公开课10 Combining multiple neural networks to improve generalization
  12. Redis:05---键的基本命令(下) 生存周期
  13. php get 数据类型,PHP基础-数据类型-integet
  14. Tomcat简单介绍
  15. 如何更省钱的在矩池云上使用pycharm
  16. Django最新版(1.10.5)在SAE上面部署流程
  17. 《使命召唤7:黑色行动》有什么简单办法进入僵尸模式
  18. FastHook——实现.dynsym段和.symtab段符号查询
  19. 轻松搭建docker应用的mesos集群
  20. MYSQL入门(一)

热门文章

  1. 为什么我现在不建议你买 5G 手机?|CSDN博文精选
  2. 那些年 iOS 升级踩过的坑!
  3. 5G 基站功耗,到底有多可怕?
  4. Python 快速入门,你想要的就在这里了!
  5. 是时候让 JavaScript 面向对象了!
  6. 看动画轻松理解「Trie树」
  7. 三招快速搞定 Linux 文件批量重命名!
  8. “人工智障”,我们还能忍你多久?
  9. 柬埔寨程序员的计算机梦想
  10. android的log.v,Android Log.v(),Log.d(),Log.i(),Log.w(),Log.e() - 何时使用每一个?