Java多线程笔记全过程(一)
一、多线程最基础的基本概念
一个程序最少需要一个进程,而一个进程最少需要一个线程。
我们常说的高并发,也并不全是线程级别的并发,在很多开发语言中,比如PHP,很常见的都是进程级别的并发。但是在Java中谈论到的基本都是线程级别的并发。当然了,高并发的来源,与摩尔定律的概念相当,等单个人无法满足任务的需求时,找多个人一起干活。就成为了主流。
这里介绍几个多线程的概念:
1.1、进程和线程:
程序:开发写的代码称之为程序。程序是一组代码,是一组数据和指令集,当然了程序是一个静态的概念。
进程:将程序运行起来,称之为进程。进程存在生命周期,随着程序的终止而销毁。进程之间通过TCP/IP端口实现交互。
线程:线程是CPU调度和执行的最小单位。PS:很多多线程都是模拟出来的,真正的多线程是指多个CPU,也就是多核,如服务器。但是如果CPU只有一个,在同一个时间点内只会执行一个代码,但是由于计算机执行速度极快,导致产生同时执行的错觉。
1.2、并发、并行、串行
并行:多个任务同时进行,但是必须具备多核能力,才能实现。
并发:同一个对象被多个线程同时操作,这一种是假并发,一个CPU可以完成工作。
串行:一个程序处理完当前进程,按照顺序处理下一个进行,一个接着一个进行。
1.3、同步和异步:
同步:当进行方法调用时,必须等到方法调用返回后,才能够执行后续行为。例子:打电话、单线程。
异步:很像是消息传递,一旦开始,调用方法就会立刻返回,调用可以继续后续行为。例子:发短信、多线程。
1.4、临界区、死锁、活锁、饥饿:
临界区:一次被一个线程占用,其他线程必须排队,例子:办公室的打印机。注意:多线程情况下,共享资源必须上锁。
死锁:在唯一性的条件下,完成任务需要A、B,但是线程1拿着A,线程2拿着B,导致双方一直在等待,形成死循环。
活锁:经典例子:孔融让梨,虽然线程们都谦让资源,但是大家都没有办法使用资源,导致任务永远完不成。这种情况下,会耗费CPU的时间。
饥饿:当线程的优先级特别低的情况下,完成线程所需要的资源永远无法获取,会造成饥饿现象。
二、线程的创建以及启动
继承Thread类,并重写run()方法。
实现Runnable接口,并重写run()方法。
通过Callable和Future创建线程
2.1.1、继承Thread类
1、自定义线程类继承Thread类
2、重写run方法,编写线程执行体
3、创建线程对象,调用start()方法
注意:创建不代表执行,需要抢CPU资源
2.1.2、代码
public class A extends Thread {
public A(String name){
super(name);
}
@Override
public void run(){
// 线程执行体
for (int i = 0; i < 10; i++) {
System.out.println("我是自定义" + Thread.currentThread().getName() + "--" + i);
}
}
public static void main(String[] args){
// 创建线程对象,准备抢占资源
A a1 = new A("线程1");
A a2 = new A("线程2");
a1.start();
a2.start();
for (int i = 0; i < 10; i++) {
System.out.println("我是主线程--" + i);
}
}
}
2.2.1 实现Runnable接口
1、自定义线程类实现Runnable接口
2、重写run方法,编写线程执行体
3、创建线程对象,调用start()方法
注意:创建不代表执行,需要抢CPU资源
2.2.2 代码
public class A implements Runnable {
@Override
public void run(){
// 线程执行体
for (int i = 0; i < 10; i++) {
System.out.println("我是自定义" + Thread.currentThread().getName() + "--" + i);
}
}
public static void main(String[] args){
// 创建线程对象,准备抢占资源
// 创建实现类对象
A myRunnable = new A();
Thread t1 = new Thread(myRunnable,"线程1");
Thread t2 = new Thread(myRunnable,"线程2");
t1.start();
t2.start();
for (int i = 0; i < 10; i++) {
System.out.println("我是主线程--" + i);
}
}
}
2.3.1 实现Callable接口(不常用)
1、实现Callable接口,先要返回值类型
2、重写call()方法,需要抛出异常
3、创建目标对象
4、创建执行服务:ExecutorService ser = Executor.newFixedThreadPool(1);
5、提交执行:Future<Boolean> res = ser.submit(t1);
6、获取结果:boolean r1 = res.get();
7、关闭服务:ser.shutdownNow();
2.3.2 代码
import java.util.concurrent.*; // 自定义线程对象,实现Callable接口,重写call()方法
public class A implements Callable<Boolean> { @Override
public Boolean call() throws Exception {
// 线程执行体
for (int i = 0; i < 10; i++) {
System.out.println("我是自定义" + Thread.currentThread().getName() + "--" + i);
}
return true;
} public static void main(String[] args) throws ExecutionException,
InterruptedException {
// main线程,主线程
// 创建线程实现类对象
A thread = new A();
A thread2 = new A();
// 创建执行服务,参数是线程池线程数量
ExecutorService ser = Executors.newFixedThreadPool(2);
// 提交执行
Future<Boolean> res = ser.submit(thread);
Future<Boolean> res2 = ser.submit(thread2);
// 获取结果
boolean r1 = res.get();
boolean r2 = res2.get();
// 关闭服务
ser.shutdownNow();
}
}
三、线程的生命周期

新建(New)状态: 创建后尚未启动(未调用start()方法)的线程处于这种状态。
就绪(Ready)状态: 当调用线程对象的start()方法,线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行。
运行(Running)状态: 当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。
限期等待(Timed Waiting)状态: 处于这种状态的线程也不会被分配CPU执行时间,不过无须等待其他线程显式地唤醒,在一定时间之后它们会由系统自动唤醒。以下方法会让线程进入限期等待状态:
新建无限期等待(Waiting)状态: 处于这种状态的线程不会被分配CPU执行时间,它们要等待被其他线程显式地唤醒。以下方法会让线程陷入无限期的等待状态。
阻塞(Blocked)状态: 线程在获取synchronized排他锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
死亡(Dead)状态: 线程执行完了或者因异常退出了run()方法,该线程生命周期结束。
Java多线程笔记全过程(一)的更多相关文章
- Java多线程笔记[未更新完]
最近课上可摸鱼时间较多,因此并发开坑学习 本篇学习自Java多线程编程实战指南 目前进展:刚开坑,处于理解概念阶段 本篇学习自Java多线程编程实战指南 Q.进程和线程的区别 进程Process是程序 ...
- Java 多线程 笔记 转自http://www.cnblogs.com/lwbqqyumidi/p/3804883.html
多线程作为Java中很重要的一个知识点, 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中 ...
- Java多线程笔记总结
1.线程的三种创建方式 对比三种方式: 通过继承Thread类实现 通过实现Runnable接口 实现Callable接口 第1种方式无法继承其他类,第2,3种可以继承其他类: 第2,3种方式多线程可 ...
- 这份java多线程笔记,你真得好好看看,我还没见过总结的这么全面的
1.线程,进程和多线程 1.程序:指指令和数据的有序集合,其本身没有任何意义,是一个静态的概念 2.进程:指执行程序的一次执行过程,是一个动态的概念.是系统资源分配的单位(注意:很多多线程是模拟出来的 ...
- Java 多线程笔记
资料来源于网络,仅供参考学习. 1.A Java program ends when all its threads finish (more specifically, when all its ...
- java多线程笔记
一,线程的状态 1,新建状态:新创建了一个线程对象 2,就绪状态:线程创建对象后,线程调用star()的方法,等待获取CPU的使用权. 3,运行状态:获取了cpu的使用权,执行程序代码 4,阻塞状态: ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
随机推荐
- Go 语言 context 都能做什么?
原文链接: Go 语言 context 都能做什么? 很多 Go 项目的源码,在读的过程中会发现一个很常见的参数 ctx,而且基本都是作为函数的第一个参数. 为什么要这么写呢?这个参数到底有什么用呢? ...
- 【WebGL系列-02】创建program上下文
WebGL程序program对象的创建 program对象由顶点着色器对象和片元着色器对象构成,因此,创建program对象包含了两部分,一个是着色器对象的创建,一个是program对象的创建. 总体 ...
- 2021-3-29 Enter按下事件
先在构造器中添加keydown事件 tBoxPsw.KeyDown += TBoxPsw_KeyDown; 在事件中添加按下enter按钮所触发的方法 private void TBoxPsw_Key ...
- python连接数据库及查询包含中文错误解决方法
使用MySQLdb库来连接数据库 import MySQLdb conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='', por ...
- 助力618-Y的混沌实践之路
一.写在前面 1.混沌是什么? 混沌工程(Chaos Engineering)的概念由 Netflix 在 2010 年提出,通过主动向系统中引入异常状态,并根据系统在各种压力下的行为表现确定优化策略 ...
- 【转自知乎】NLP算法面试必备!史上最全!PTMs:NLP预训练模型的全面总结
NLP算法面试必备!史上最全!PTMs:NLP预训练模型的全面总结 预训练模型(Pre-trained Models,PTMs)的出现将NLP带入了一个全新时代.2020年3月18日,邱锡鹏老师发表了 ...
- quarkus依赖注入之九:bean读写锁
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<quarkus依赖注入> ...
- call与retn指令
一. call指令 将call指令下一跳指令压入栈中 jmp跳转到call指令的地址 二. retn指令 pop指令将栈顶元素弹出存储 jmp跳转到该栈顶元素地址 retn n;表示再前两步操作的基础 ...
- AI绘画:StableDiffusion制作AI赛博机车图保姆级教程
本教程收集于:AIGC从入门到精通教程汇总 如果你具备Stable Diffusion的基础知识,那制作AI赛博机车图会更为顺畅.即便没有这个基础,只要严格按照教程的步骤执行,也能成功制作出来. 本教 ...
- 1Nginx基础及编译安装
1Nginx基础 1.Nginx概述 Nginx 功能介绍 Nginx(发音为"engine-x")是一个开源的高性能 HTTP和反向代理服务器.它具有以下功能: 1.静态文件服务 ...