【Java系列】【基础版】多线程基础

  1. 多线程基础

1.1 认识进程和线程

1.1.1 什么是进程

1.1.1.1 进程是正在进项的程序,是资源分配的一个基本单位,有内存分配;

1.1.2 什么是线程

1.1.2.1 线程是进程的一个执行单位,也是进程的执行顺序;

1.1.2.2 一个进程至少有一个线程,可以由两个或以上的线程;

1.1.3 JVM至少有几个线程

1.1.3.1 至少有一个或两个线程,main方法和垃圾回收线程;

1.1.4 什么是多线程

1.1.4.1 2个或以上的线程去执行

1.1.5 多线程的作用

1.1.5.1 提高效率,线程之间切换的小号是可以接受的;

1.1.5.2 单线程容易阻塞;

1.1.5.3 多个线程同时执行代码;

1.1.5.4 一个线程挂了,还有其他的线程在,程序还在执行

1.1.6 进程和线程是谁创建的

都是操作系统创建的

1.1.7 如何自定义一个线程

1.1.7.1 继承Thread类,重写run方法

1.1.7.2 生成对象

1.1.7.3 开启start

1.1.8 所有实现的接口

1.1.8.1 Runnable接口

1.1.8.2 new线程对象的时候,创建了线程

1.1.8.3 start方法,沟通了操作系统,告诉操作系统有一个线程要开启,也调用了run

1.2 代码示例

1.2.1 在main主线程里,再度开启其他线程

1.2.1.1 测试类:

public class Test {

public static void main(String[] args) throws ParseException  {

Test001 t = new Test001();//这里代表着产生了一个线程

Test001 t1 = new Test001();//这里代表着产生了一个线程

System.out.println("开启线程之前");

//t1.run();//代表着调用了对象的方法

t.start();//这里代表开启了一个线程,是沟通了操作系统

t1.start();//这里代表开启了一个线程,是沟通了操作系统

try {

Thread.sleep(15);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("开启线程之后");

System.out.println("main  over");

}

}

1.2.1.2 重写run方法类,继承Thread类:

class Test001 extends Thread{

@Override

public void run() {

for (int i = 0; i < 100; i++) {

try {

sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("run    .. "+i);

}

}

}

1.2.2 创建一个线程,和主程序交替执行

1.2.2.1 测试类

public class ThreadTest {

public static void main(String[] args) {

Test t = new Test();

t.start();

for (int i = 0; i < 10; i++) {

System.out.println("main>>>"+i);

}

System.out.println("main  -  gg");

}

}

1.2.2.2 方法类

class Test extends Thread{

int i = 0;

@Override

public void run() {

while(true){

if(i<10){

System.out.println("run方法..." + i++);

}else{

System.out.println("run  - OVER");

break;

}

}

}

}

1.2.3 模拟买票功能

1.2.3.1 测试类

public class TestRunnable01 {

public static void main(String[] args) {

Runnable x1 = new XinXiaoMi();

Thread t1 = new Thread(x1);

Thread t2 = new Thread(x1);

Thread t3 = new Thread(x1);

t1.setName("小红");

t2.setName("小蓝");

t3.setName("小绿");

t1.start();

t2.start();

t3.start();

}

}

1.2.3.2 方法类

class XinXiaoMi implements Runnable{

static int i =100;//共享的

Object o = new Object();

@Override

public void run() {

boolean b = true;

while(b){

synchronized (o) {

if(i>0){//i = 1

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"...卖出了手机,编号是..." + i--);

}

else{

break;

}

}

}

}

}

1.2.4 小明和老婆同时存钱,每次存取500元,每人存5次

1.2.4.1 测试类:

public class TestRunnable02 {

public static void main(String[] args) {

test t = new test();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

t1.setName("小明");

t2.setName("陈学冬");

t1.start();

t2.start();

}

}

1.2.4.2 方法类:

class test implements Runnable{

int con = 0;//初始定义了账户余额为0元

Object o = new Object();

@Override

public void run() {

synchronized (o) {

for (int i = 0; i < 5; i++) {

con += 500;

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"  存了500大洋---此时账户余额为  。。"+con);

}

}

}

}

1.2.4 小明和老婆同时存钱,每次存取500元,每人存5次; 同时实现方法的同步

1.2.4.1 测试类

public class TestM {

public static void main(String[] args) {

test00 t = new test00();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

t1.setName("小明");

t2.setName("baby");

t2.start();

t1.start();

}

}

1.2.4.2 方法类

class test00 implements Runnable{

int con = 0;//初始定义了账户余额为0元

Object o = new Object();

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+" 到达房间门口");

this.show();//一次就好,许你地老天荒

}

public synchronized void show(){

System.out.println(Thread.currentThread().getName()+" 锁住了房间");

for (int i = 0; i < 5; i++) {

con += 500;

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"  存入了500,此时余额是    "+con);

}

System.out.println(Thread.currentThread().getName()+" 离开了房间,打开了锁");

}

}

1.2.5 小明和老婆同时存钱,每次存取500元,每人存5次; 同时实现方法的同步;同时实现交替存储

1.2.5.1 测试类

public class TestM2 {

public static void main(String[] args) {

test000 t = new test000();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

t1.setName("小明");

t2.setName("baby");

t2.start();

t1.start();

}

}

1.2.5.2 方法类

class test000 implements Runnable{

int con = 0;//初始定义了账户余额为0元

Object o = new Object();

@Override

public void run() {

for (int i = 0; i < 5; i++) {

//等待区

show();

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public synchronized void show(){

System.out.println(Thread.currentThread().getName()+" 上锁了");

con += 500;

System.out.println(Thread.currentThread().getName()+"  存入了  500 ,  此时余额为   "+con);

System.out.println(Thread.currentThread().getName()+" 锁开了");

}

}

1.2.6 死锁的示例

1.2.6.1 测试类:

/* Runnablere =new Runnable() {

public void run() {

}

};

*/

public class Test01 {

public static void main(String[] args) {

TestSY ts1 = new TestSY();

Thread th1 = new Thread(ts1);

Thread th2= new Thread(ts1);

th1.start();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

TestSY.b = false;

th2.start();

}

}

1.2.6.2 方法类:

class TestSY implements Runnable{

static boolean b = true;

Object o = new Object();

Object o1 = new Object();

@Override

public void run() {

if( b ){

synchronized (o) {

System.out.println("if  拿到了 o 的锁");

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (o1) {

System.out.println("if-----");

}

}

}else{

synchronized (o1) {

System.out.println("else  拿到了 o1 的锁");

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (o) {

System.out.println("else-----");

}

}

}

}

}

1.3 cpu调度

cpu的时间片,cpu控制着执行;

cpu会自行分配资源给线程,得到资源的线程可以执行,没有得到资源的线程没有办法执行;

多个cpu才是真正意义上的同时执行多线程,因为运行速度特别多,会给我们产生错觉,认为是同时执行的;

1.4 线程的状态

1.4.1 新生

1.4.1.1 new对象的时候代表着新生;

1.4.2 就绪

1.4.2.1 start方法代表着就绪,这个时候在等待着CPU的资源;如果有资源就进入执行状态,没有资源就继续等待;

1.4.3 执行

1.4.3.1 拿到时间片,正在执行;时间片被拿走了就离开了执行状态;

1.4.4 阻塞

1.4.4.1 睡觉sleep,让资源;时间结束了就回到就绪状态,等待资源;

1.4.5 死亡

1.4.5.1 线程执行结束;非正常死亡方式;

1.5 两种创建线程方式的比较

1.5.1 继承方式创建简单,使用的方法也多;

1.5.2 java是单继承的,使用集成方式过于死板;

1.5.3 继承是不共享资源的,实现方式是共享的;

1.5.4 主要由于单继承的机制,推荐使用Runnable接口实现这种方式

1.5.4.1 实现接口,重写方法

1.5.4.2 new一个对象

1.5.4.3 把new的对象放进线程(Thread)对象里

1.5.4.4 用线程对象开启线程

1.5.4.5 注意:run方法不能抛异常

1.6 同步代码块原理解析

1.6.1 java提供了锁的机制synchronized ,可以锁住一段代码,在任何时期这段代码里面最多只有一个线程在执行。每个要进来的线程都会先判断此处有没有上锁。

1.6.1.1 如果没有,就进去并且上锁,再执行完之后才会离开,同时打开锁,其他的线程才可以进来

1.6.1.2 如果被锁,再门口等待,进不去; 这里锁,锁的是对象。具体锁那个对象呢。具体情况具体分析

1.6.2 同步的优缺点

1.6.2.1 同步的前提

1.6.2.1.1 两个或两个以上的线程去操作共享数据时

1.6.2.2 同步的好处

1.6.2.2.1 保证了线程的安全性

1.6.2.3 同步的缺陷

1.6.2.3.1 消耗增加,但是影响不大

1.6.2.3.2 使用不当容易造成死锁

时间: 2024-07-30 23:40:45

【Java系列】【基础版】多线程基础的相关文章

《java编程思想》--多线程基础--Runnable

一.简单说下Runnable是什么 1.它是一个接口 2.只提供了run方法 3.这个接口提供了一个协议:实现这个接口的类是active的(不必成为Thread的子类) 1 /** 2 * The <code>Runnable</code> interface should be implemented by any 3 * class whose instances are intended to be executed by a thread. The 4 * class mu

java 内存模型和多线程基础

【基础版限时免费】致敬WebForms,ASP.NET Core也能这么玩!

ASP.NET WebForms ASP.NET WebForms 随着微软 2000 年的 .Net Framework 一起发布,至今也将近 20 年的时间.相信很多人和我一样,对 WebForms 有着割舍不掉的感情, 直至今日 WebForms 仍然在管理系统快速开发领域有着不可替代的作用! 基于 ASP.NET WebForms 的 FineUI(开源版)在结束了 9 年 130 个版本的迭代后,继任者 FineUIPro(企业版)也持续了 5 年 30 多个版本的迭代,目前已经非常成

[转]Java多线程干货系列—(一)Java多线程基础

Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的执行单元线程本身依靠程序进行运行线程是程序中的顺序控制流,只能使用分配给程序的资源和环境 2 进程:执行中的程序一个进程至少包含一个线程 3 单线程:程序中只存在一个线程,实际上主方法就是一个主线程 4

Java多线程基础(一)

线程与进程 1 线程:进程中负责程序执行的执行单元线程本身依靠程序进行运行线程是程序中的顺序控制流,只能使用分配给程序的资源和环境 2 进程:执行中的程序一个进程至少包含一个线程 3 单线程:程序中只存在一个线程,实际上主方法就是一个主线程 4 多线程:在一个程序中运行多个任务目的是更好地使用CPU资源 5  在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性. 每个对象都对应于一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访问对象用关键字synchr

Java多线程基础

1. 前言 这篇文章,是对Java多线程编程的基础性介绍. 文章将介绍Java语言为支持多线程编程提供的一些特性.通过这篇文章,您将了解到如何通过Java语言创建一个线程,如何通过内置的锁来实现线程间的同步,如何在线程间进行通信以及线程的中断机制. 2. 什么是线程 线程是操作系统调度的最小单位,在一个进程中,一般至少有一个线程在运行.一个进程中包含的多个线程,在多核处理器中,操作系统可以将多个线程调度到不同的CPU核心上运行,多个线程可以并行运行. 在同一个进程中的多个线程,共享同一个进程空间

Java多线程基础(四)Java传统线程同步通信技术

Java多线程基础(四)Java传统线程同步通信技术 编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声

多线程系列(1)多线程基础和Thread

因为现项目中有用到多线程和并发的知识,所以打算近期补习一下多线程相关的内容.第一篇文章从最基础的开始,就是如何开启一个线程,如何启动线程和阻塞线程等,这篇文章分以下几点进行总结. 多线程初印象 多线程的使用场景 线程的启动,挂起和终止 一个简单的多线程实例 多线程初印象 首先通过一张图来了解一下进程Process,应用程序域AppDomain和线程Thread之间的关系. 从图中可以总结出以下几点: 一个进程Process可能包含多个应用程序域,也包含多个线程,线程也可以穿梭于多个应用程序域当中

Java基础笔记(四:多线程基础及生命周期)

一.多线程基础 编写线程程序主要是构造线程类.构造线程类的方式主要有两种,一种是通过构造类java.lang.Thread的子类,另一种是通过构造方法实现接口java.lang.Runnable的类.因为类java.lang.Thread实际上也是实现了接口java.lang.Runnable的类,所以上面两种构造线程类的方法从本质上都是构造实现接口java.lang.Runnable的类.下面将具体介绍着两种方法. (1)通过类Thread的子类构造线程 类java.lang.Thread的每