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()方法.该状态的线程位于可运行线程池中, ...
随机推荐
- Java杂记————object.getClass()和object.class以及Java中的toString()方法的的区别
不说废话,直接上干货: (注意大小写:object为对象,Object为类) 1,object.getClass()它是Object类的实例方法,返回一个对象运行时的类的Class对象,换句话说,它返 ...
- 如何制作 GitHub 个人主页
人们在网上首先发现你的地方是哪里?也许你的社交媒体是人们搜索你时首先发现的东西,亦也许是你为自己创建的投资组合网站.然而,如果你使用GitHub来分享你的代码并参与开源项目,那么你的GitHub个人主 ...
- Kotlin 常用语法糖记录
原文地址: Kotlin 常用语法糖记录 - Stars-One的杂货小窝 当使用 Kotlin 编程时,有一些常用的函数可以帮助我们简化代码并提高开发效率. 稍微列举下常用的方法 runCatchi ...
- CF961E Tufurama题解
我们维护一个存储下标数据的树状数组,先将 \(1\sim n\) 插入树状数组. 用 \(a\) 表示原数组,\(b\) 表示按照 \(a_i\) 排序后的数组. 我们从 \(1\) 开始统计,直到 ...
- 【阅读笔记】低照度图像增强-《An Integrated Neighborhood Dependent...
本文介绍的是一种比较实用的低照度图像增强算法,选自2004年Tao的一篇论文,名称是<An Integrated Neighborhood Dependent Approach for Nonl ...
- Maven配置UTF8,JDK版本
<!-- 局部jdk配置,pom.xml中 --> <build> <plugins> <plugin> <groupId>org.apac ...
- matlab2014a破解不完全,报错Test checkout of feature 'Compiler' failed
解决方案 报错情况: 目标是把.m文件转化为.exe文件,先运行 mcc -m 你的文件.m 如果报错 Test checkout of feature 'Compiler' failed 是因为你的 ...
- C# 12新预览功能介绍
Visual Studio 17.7 Preview 3和.NET 8 Preview 6延续了C# 12的发展.该预览版包含的功能旨在为未来的性能增强奠定基础.对内联数组的轻松访问将允许库在更多地方 ...
- TrustZone——(一)
本文内容主要来源于网络,综合了网上的多篇文章,也加入了一些自己的理解,重新组织了文章结构使其便于理解. 主要参考的文章包括: 一篇了解TrustZone TrustZone领域先行者 TrustZon ...
- Blazor中CSS隔离无法用在子组件内部
Blazor的CSS隔离是个很好的东西,如图,只需添加一个与Razor组件同名的CSS文件,这个文件中的CSS样式只会在同名的Razor组件中使用. 原理是通过在dom元素添加一个代表标识符的属性 在 ...