本份随记主要为狂神老师的Java多线程教学的学习笔记,记载了视频中一些有关基础概念以及部分代码示例。随机分为1-3共三份,知识点记录的不是很深入,以后的学习过程中随时补充。

1 有关基础概念

1.1 核心概念

  1. 线程就是独立的执行路径
  2. 程序运行时,即使没有自己创建线程,后台也会由多个线程(主线程、gc线程)
  3. main()称之为主线程,为系统的入口,用于执行整个程序
  4. 一个进程中,若开辟多个线程,线程的运行由调度器安排调度,调度器与操作系统紧密相关,先后顺序不能被人为干预。
  5. 对同一份资源操作时,会存在资源抢夺问题,需加入并发控制
  6. 线程会带来额外的开销(cpu调度时间,并发控制开销)
  7. 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致(队列和锁)。

1.2 程序、进程、线程

  1. 程序(静态概念):程序是指令和数据的有序集合,本身没有任何运行的含义
  2. 进程(动态概念):程序的一次执行过程,是系统资源分配的单位
  3. 线程:CPU调度和分派的基本单位。(进程中可包含至少一个的若干线程)
  4. 进程 vs 线程:

    同一进程中的线程使用相同的地址空间,而不同的进程则不会。这允许线程读写公共共享和数据结构和变量,也增加了线程之间的通信。然而,进程间通信(即IPC)是非常困难的,并且需要耗费大量资源。

1.3 并发、并行

  1. 并行:两个或多个事务在同一时刻发生。

    实际多线程为并行执行:多个cpu(多核)共同执行线程。
  2. 并发:两个或多个事务在同一时间间隔内发生。

    模拟多线程为并发执行:在一个cpu情况下同一时间点只能执行一个线程,但切换很快。

2 线程创建

2.1 Thread class(继承Thread类)

  1. 自定义线程类继承Thread类
  2. 子类重写父类的run方法,编写程序执行体
  3. 分配并启动子类的实例(创建线程对象,调用start方法启动线程)

程序示例:

点击查看代码
// 1.创建子类继承自Thread类
public class CreateThread extends Thread{ //2.重写run方法
@Override
public void run() {
for(int i = 0; i < 5; i++){
System.out.println("Run.No." + i);
}
}
public static void main(String[] args){
//3.创建一个线程对象
CreateThread createThread1 = new CreateThread();
//3.调用start方法开启线程
createThread1.start();
for (int i = 0; i < 5; i++) {
System.out.println("No." + i);
} }
}

注: 线程开启不一定立即执行,由CPU调度执行,线程执行顺序不是由定义顺序决定的。

2.2 Runnable接口的实现

  1. 定义MyRunnable类实现Runnable接口
  2. 实现run方法,编写程序执行体
  3. 创建线程对象(代理),调用start方法启动线程。

    new Thread(implementRunnable1).start();

程序示例:

点击查看代码
// 1.实现runnable接口
public class ImplementRunnable implements Runnable{ //2.重写run方法
@Override
public void run() {
for(int i = 0; i < 200; i++){
System.out.println("Run.No." + i);
}
}
public static void main(String[] args){
//3.1 创建一个接口实现类对象
ImplementRunnable implementRunnable1 = new ImplementRunnable();
//3.2 创建线程对象,通过线程对象开启线程(代理)
Thread thread = new Thread(implementRunnable1);
// 3.3调用线程start方法
thread.start();
// 3-归并
new Thread(implementRunnable1).start();
for (int i = 0; i < 5; i++) {
System.out.println("No." + i);
} }
}

2.3 Thread与Runnable的对比

2.3.1 继承Thread类:

  1. 创建方法:子类继承Thread类具备多线程能力
  2. 启动线程方法:子类对象.start()
  3. 不建议使用:避免单继承局限性

2.3.2 实现Runnable接口:

  1. 实现接口Runnable具有多线程能力
  2. 启动线程方法:new Thread(传入目标对象).start()
  3. 推荐使用:避免了单继承局限性,灵活方便,方便同一对象被多个线程使用。

2.4 Callable接口(了解)

  1. 实现Callable接口,需返回值类型
  2. 重写call方法,需抛出异常
  3. 创建目标对象
  4. 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
  5. 提交执行:Future<Boolean> result1 = ser.submit(t1);
  6. 获取结果:boolean r1 = result1.get();
  7. 关闭服务:ser.shutdownNow();

优缺点分析:

  1. 可以定义返回值
  2. 可以抛出异常
  3. 实现方式较为复杂

3 静态代理

示例:婚庆公司结婚模型(你去结婚,婚庆公司帮你结婚)

内容:

  1. 结婚接口Marry
  2. 你You:参与结婚的角色
  3. 婚庆公司WeddingCompany: 代理角色,帮你完成结婚这件事
  4. 比较Thread,婚庆公司~Thread, You~要调用的线程对象(实现runnable接口的类),thread代替接口实现类去做一些事情

    new WeddingCompany(new You("Mike")).HappyMarry();

    new Thread(() -> System.out.println("I love you!")).start();

模式总结:

  1. 真实对象和代理对象都要实现同一个接口
  2. 代理对象要代理真实角色
  3. 优势
    1. 代理对象可以做很多真实对象不愿做或无法做的事
    2. 真实对象专注做自己的事

4 线程状态

线程可以处于以下状态之一:

  1. NEW: 尚未启动的线程处于此状态。
  2. RUNNABLE:在Java虚拟机中执行的线程处于此状态。
  3. BLOCKED:被阻塞等待监视器锁定的线程处于此状态。
  4. WAITING:正在等待另一个线程执行特定动作的线程处于此状态。
  5. TIMED_WAITING:正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
  6. TERMINATED:已退出的线程处于此状态。

一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。


与此有关的一些线程方法

4.1 线程停止

  1. 不推荐JDK提供的stop,destroy方法[已过时 @Deprecated]
  2. 推荐线程自行停止(利用次数,不建议死循环)
  3. 建议使用标志位进行终止变量,当flag=false则终止线程运行。

4.2 线程休眠(sleep)

  1. sleep(时间)指定当前线程阻塞的毫秒
  2. sleep存在异常InterruptedException
  3. sleep时间打倒后线程进入就绪状态
  4. sleep可以模拟网络延时,倒计时等
  5. 每个对象都有一个锁,sleep不会释放锁

4.3 线程礼让(yield)

概念: 让当前正在执行的线程暂停,但不阻塞(将线程从运行状态转为就绪状态)。

礼让为让CPU重新调度,因此礼让成功与否取决于CPU。

4.4 线程强制执行(join)

Join合并线程,待此线程执行完成后再执行其他线程,其他线程阻塞。

类似于VIP插队

4.5 线程状态观测(Thread.State)

线程状态State为Thread类中的枚举类型:

public static enum Thread.State extends Enum<Thread.State>

获取线程状态的方法:

Thread.State state = thread.getState(); System.out.println(state);

4.6 线程优先级

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定该调度哪个线程来执行。

范围:线程优先级用数字表示[1, 10]

Thread.MIN_PRIORITY = 1; Thtead.MAX_PRIORITY = 10

改变/获取线程优先级:

getPriority(), setPriority(int xxx)

注:先设置优先级再启动;优先级低只是意味着获得调度的概率低。

4.7 守护线程(daemon)

  1. 线程分为用户线程和守护线程
  2. 虚拟机必须确保用户线程执行完毕(main)
  3. 虚拟机不用等待守护线程执行完毕(gc)
  4. 守护线程:后台记录操作日志,监控内存,垃圾回收等

Java多线程-1(3)的更多相关文章

  1. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  2. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  3. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  4. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  5. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  6. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  7. java 多线程 1 线程 进程

    Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报  分类: javaSE综合知识点(14)  版权声明:本文为博主原创文章,未经博 ...

  8. 一起阅读《Java多线程编程核心技术》

    目录 第一章 Java多线程技能 (待续...)

  9. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  10. java从基础知识(十)java多线程(下)

    首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...

随机推荐

  1. Spring学习03(Bean的自动装配)

    6.Bean的自动装配 6.1 自动装配说明 自动装配是使用spring满足bean依赖的一种方法 spring会在应用上下文中为某个bean寻找其依赖的bean. Spring中bean的三种装配机 ...

  2. SpringBoot开发八-会话管理

    需求介绍-会话管理 利用Cookie和Seesion使得HTTP变成有会话的连接,写几个实例演示一下 代码实现 先写个例子,表示客户端第一次访问服务器,服务器端创建一个Cookie发送给客户端. 不管 ...

  3. E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?

    E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)E: Unable to l ...

  4. 做iOS自动化测试必须知道的一些知识

    WDA facebook wda 2015年Facebook 开源了一款 iOS 移动测试框架WebDriverAgent,WebDriverAgent 在 iOS 端实现了一个 WebDriver ...

  5. HTML界的“苏炳添”——详解Canvas优越性能和实际应用

    Google Docs宣布将会把HTML迁移到基于Canvas渲染,这一消息的出现再次把几年前随HTML5诞生的标签重新推到了人们视线之中.Canvas在刚推出时主打的优势就是更快的渲染速度,堪称HT ...

  6. Centos7上yum安装redis

    下载tar包 wget http://download.redis.io/releases/redis-6.0.5.tar.gz 解压tar包 tar -zxvf redis-6.0.5.tar.gz ...

  7. MongoDB 数据库创建删除、表(集合) 创建删除、数据增删改查

    使用数据库.创建数据库 use student 如果真的想把这个数据库创建成功,那么必须插入一个数据. 数据库中不能直接插入数据,只能往集合(collections)中插入数据.不需要专门创建集合,只 ...

  8. 伪静态是什么?伪静态与普通html静态网页区别?

    什么是伪静态,伪静态作用伪静态即是网站本身是动态网页如.php..asp..aspx等格式动态网页有时这类动态网页还跟"?"加参数来读取数据库内不同资料.很典型的案例即是discu ...

  9. Windows 10 - View SIM Card Number

     If your device isn't running Windows 10, refer to the Windows 8 instructions. From the Windows desk ...

  10. 【linux】tail 命令详解

    转自:https://www.cnblogs.com/fps2tao/p/7698224.html Linux命令:显示文件结尾 Head/Tail head 与 tail 就像它的名字一样的浅显易懂 ...