本份随记主要为狂神老师的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. 用notepad2代替notepad

    Windows自带的notepad.exe功能比较弱,notepad2是一个比较好的替代方案,但在任何系统调用notepad的时候都能用notepad2代替并不是一件容易的事,下面是一个解决方法: h ...

  2. 1051 Pop Sequence (25分)栈

    刷题 题意:栈的容量是5,从1~7这7个数字,写5个测试数据 做法:模拟栈 #include<bits/stdc++.h> using namespace std; const int m ...

  3. 【原创】一文彻底搞懂安卓WebView白名单校验

    前言 近两年公司端侧发现的漏洞很大一部分都出在WebView白名单上,针对这类漏洞安全编码团队也组织过多次培训,但是这种漏洞还是屡见不鲜.下面本人就结合产品中容易出现问题的地方,用实例的方式来总结一下 ...

  4. CTF--[BJDCTF2020]Cookie is so stable 1(SSTI)

    从hint.php可以找到提示,要求观察cookies 打开flag.php可以看到需要输入用户名,多次试验后发现输入的用户名会以cookies的方式储存 使用dirsearch扫描没有发现什么有用的 ...

  5. SQL 练习4

    查询不存在" 01 "课程但存在" 02 "课程的情况 SELECT * from sc WHERE cid = '02' AND sid not in (SE ...

  6. MyBatiesPlus+Redis分布式缓存

    一.开启二级缓存 cache-enabled: true # mybatis-plus相关配置 mybatis-plus: # xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 X ...

  7. dubbo暴露原理及引用过程

    服务暴露 服务引用:

  8. Linux下MySQL主从复制(GTID)+读写分离(ProxySQL)-实施笔记

    GTID概念: GTID( Global Transaction Identifier)全局事务标识.GTID 是 5.6 版本引入的一个有关于主从复制的重大改进,相对于之前版本基于 Binlog 文 ...

  9. Ubuntu中配置tomcat

    1.从网上下载的tomcat配置失败后,servername那一栏写不了,必须要删除工作空间的配置文件 sudo rm /home/{username}/workspace/.metadata/.pl ...

  10. vue 基础入门(一)

    app-1 :声明式渲染 app-2 :绑定元素特性 v-bind 特性被称为指令.指令带有前缀 v-,以表示它们是 Vue 提供的特殊特性. app-3 app-4 :条件与循环 app-5 ,ap ...