Java多线程-1(3)
本份随记主要为狂神老师的Java多线程教学的学习笔记,记载了视频中一些有关基础概念以及部分代码示例。随机分为1-3共三份,知识点记录的不是很深入,以后的学习过程中随时补充。
1 有关基础概念
1.1 核心概念
- 线程就是独立的执行路径
- 程序运行时,即使没有自己创建线程,后台也会由多个线程(主线程、gc线程)
- main()称之为主线程,为系统的入口,用于执行整个程序
- 一个进程中,若开辟多个线程,线程的运行由调度器安排调度,调度器与操作系统紧密相关,先后顺序不能被人为干预。
- 对同一份资源操作时,会存在资源抢夺问题,需加入并发控制
- 线程会带来额外的开销(cpu调度时间,并发控制开销)
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致(队列和锁)。
1.2 程序、进程、线程
- 程序(静态概念):程序是指令和数据的有序集合,本身没有任何运行的含义
- 进程(动态概念):程序的一次执行过程,是系统资源分配的单位
- 线程:CPU调度和分派的基本单位。(进程中可包含至少一个的若干线程)
- 进程 vs 线程:
同一进程中的线程使用相同的地址空间,而不同的进程则不会。这允许线程读写公共共享和数据结构和变量,也增加了线程之间的通信。然而,进程间通信(即IPC)是非常困难的,并且需要耗费大量资源。
1.3 并发、并行
- 并行:两个或多个事务在同一时刻发生。
实际多线程为并行执行:多个cpu(多核)共同执行线程。 - 并发:两个或多个事务在同一时间间隔内发生。
模拟多线程为并发执行:在一个cpu情况下同一时间点只能执行一个线程,但切换很快。
2 线程创建
2.1 Thread class(继承Thread类)
- 自定义线程类继承Thread类
- 子类重写父类的run方法,编写程序执行体
- 分配并启动子类的实例(创建线程对象,调用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接口的实现
- 定义MyRunnable类实现Runnable接口
- 实现run方法,编写程序执行体
- 创建线程对象(代理),调用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类:
- 创建方法:子类继承Thread类具备多线程能力
- 启动线程方法:子类对象.start()
- 不建议使用:避免单继承局限性
2.3.2 实现Runnable接口:
- 实现接口Runnable具有多线程能力
- 启动线程方法:new Thread(传入目标对象).start()
- 推荐使用:避免了单继承局限性,灵活方便,方便同一对象被多个线程使用。
2.4 Callable接口(了解)
- 实现Callable接口,需返回值类型
- 重写call方法,需抛出异常
- 创建目标对象
- 创建执行服务:
ExecutorService ser = Executors.newFixedThreadPool(1);
- 提交执行:
Future<Boolean> result1 = ser.submit(t1);
- 获取结果:
boolean r1 = result1.get();
- 关闭服务:
ser.shutdownNow();
优缺点分析:
- 可以定义返回值
- 可以抛出异常
- 实现方式较为复杂
3 静态代理
示例:婚庆公司结婚模型(你去结婚,婚庆公司帮你结婚)
内容:
- 结婚接口Marry
- 你You:参与结婚的角色
- 婚庆公司WeddingCompany: 代理角色,帮你完成结婚这件事
- 比较Thread,婚庆公司~Thread, You~要调用的线程对象(实现runnable接口的类),thread代替接口实现类去做一些事情
new WeddingCompany(new You("Mike")).HappyMarry();
new Thread(() -> System.out.println("I love you!")).start();
模式总结:
- 真实对象和代理对象都要实现同一个接口
- 代理对象要代理真实角色
- 优势
- 代理对象可以做很多真实对象不愿做或无法做的事
- 真实对象专注做自己的事
4 线程状态
线程可以处于以下状态之一:
- NEW: 尚未启动的线程处于此状态。
- RUNNABLE:在Java虚拟机中执行的线程处于此状态。
- BLOCKED:被阻塞等待监视器锁定的线程处于此状态。
- WAITING:正在等待另一个线程执行特定动作的线程处于此状态。
- TIMED_WAITING:正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
- TERMINATED:已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。
与此有关的一些线程方法
4.1 线程停止
- 不推荐JDK提供的stop,destroy方法[已过时 @Deprecated]
- 推荐线程自行停止(利用次数,不建议死循环)
- 建议使用标志位进行终止变量,当flag=false则终止线程运行。
4.2 线程休眠(sleep)
- sleep(时间)指定当前线程阻塞的毫秒
- sleep存在异常InterruptedException
- sleep时间打倒后线程进入就绪状态
- sleep可以模拟网络延时,倒计时等
- 每个对象都有一个锁,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)
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕(main)
- 虚拟机不用等待守护线程执行完毕(gc)
- 守护线程:后台记录操作日志,监控内存,垃圾回收等
Java多线程-1(3)的更多相关文章
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程基础知识篇
这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程--让主线程等待子线程执行完毕
使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...
- Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- java 多线程 1 线程 进程
Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报 分类: javaSE综合知识点(14) 版权声明:本文为博主原创文章,未经博 ...
- 一起阅读《Java多线程编程核心技术》
目录 第一章 Java多线程技能 (待续...)
- 第一章 Java多线程技能
1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
- java从基础知识(十)java多线程(下)
首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...
随机推荐
- 第6篇-Java方法新栈帧的创建
在 第2篇-JVM虚拟机这样来调用Java主类的main()方法 介绍JavaCalls::call_helper()函数的实现时提到过如下一句代码: address entry_point = me ...
- Sqli-Labs less8-10
less-8 前置基础知识: 前几关我们用到了布尔盲注的办法,还有一种盲注就是时间盲注,不仅可以用于有回显的盲注,还能用于没有回显的盲注 函数:sleep(1):等待1秒之后再返回页面做出反应 IF( ...
- SQL 练习23
查询男生.女生人数 SELECT Ssex,COUNT(Ssex) 人数 from Student GROUP BY Ssex
- noip33
T1 第一个猎人死的轮数等于在1号猎人之前死的猎人数+1,如果当前这个人没死,那么他死在一号猎人之前的概率为 \(\frac{w_{i}}{w_{1}+w_{i}}\),因为每死一个就会造成1的贡献, ...
- Linux 记录学习
- C# 多线程刷新UI
2.利用委托调用--最常见的办法(仅WinForm有效) using System; using System.Threading; using System.Windows.Forms; nam ...
- C# volatile 的使用
class Program { private static volatile bool bChanged; static void Main(string[] args) { Thread t1 = ...
- 【转】SpringCloud学习
Spring Cloud Alibaba与Spring Boot.Spring Cloud之间不得不说的版本关系 这篇博文是临时增加出来的内容,主要是由于最近连载<Spring Cloud ...
- cmd进入pycharm所创建的虚拟环境
进入cmd命令,进入虚拟环境所在文件夹.(pycharm每创建一个新项目就会创建一个虚拟环境,位于项目下venv下Script) E:\virtualenv\crawl1\Scripts>act ...
- ARP协议工作原理实验
一.实验目的 验证"在向目的主机发送数据包时会先查询ARP高速缓存,如果ARP高速缓存中已保存了目的主机的MAC地址,不进行ARP查询,使用ARP高速缓存中的MAC地址:如果缓存中没有IP对 ...