Java多线程笔记总结

线程概述

一个电脑运行的应用程序是一个进程,一个进程至少有一个线程,一个进程可以包含多个线程

Java的集合有线程安全与线程不安全的集合,线程安全指的是同步(排队执行,效率低但是安全),线程不安全指的是异步(同时执行,效率高但是数据不安全)

线程的实现方式分为并发与并行,并发指的是两个或多个事件在同一时间段内发生,并行指两个或多个事件在同一时刻发生

线程调度

1分时调度:所有线程轮流使用cpu的使用权,平均分配每个线程占用CPU的时间

2抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度

创建新执行线程有三种方法。

第一种方法是将类声明为Thread的子类。

该子类重写Thread类的run方法。在run方法中设置线程任务。启动多线程:创建一个实现类对象,并且调用start()方法,来启动多线程

第二种方法是实现Runnable接口

实现步骤

1创建一个Runnable接口的实现类

2在实现类中重写Runnable接口的run方法,设置线程任务

3创建一个Runnable接口的实现类对象(也称为任务对象)

4创建Thread类对象,构造方法中传递Runnable接口的实现类对象(也可以描述为:创建了一个线程,并为其分配一个任务)

5调用Thread类中的start方法,开启新的线程,执行run方法(执行这个任务)

第三种方式-Callable(带返回值的线程)

Callable常用的方法

get():获取线程执行的结果

isDone():判断子线程是否执行完毕

task.cancel():取消Callable的任务执行

Thread类的常用方法

01-获取线程名称

获取线程的名称:(有两种方法)

1使用Thread类中的方法getName():使用它可以获取当前线程的名称

String getName() :返回值为String,返回该线程的名称

2可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称

static Thread currentThread()

currentThread()方法,它是一个静态的方法,它的返回值就是一个Thread

02设置线程名称

两种方式:

1使用Thread类中的方法setName();

void setName(String name):改变线程名称,使之与参数name相同

2创建一个带参数的构造方法,参数传递线程的名称,调用父类的带参构造方法,把线程名称传递给父类,让父类Thread给子线程起一个名字

Thread(String name):分配新的Thread对象

03让线程睡眠sleep()

public static void sleep(long millis):是当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),毫秒数结束之后,线程继续执行

04Thread类的常用方法-设置线程的优先级

setPriority(int newPriority):更改此线程的优先级

getPriority:获取此线程的优先级

线程可以拥有的最大优先级MAX_PRIORITY,还有最低优先级和默认优先级,可以去API中查看,这三个优先级可以通过setPriority()方法,控制线程抢到时间篇的几率

解决线程安全问题-线程同步技术

有三种方式完成同步操作

1同步代码块

2同步方法

3Lock锁机制

1同步代码块

格式:

synchronized(同步锁){

需要同步操作的代码

}

同步代码块就是一个代码块,一对大括号,里面放可能出现线程安全的代码,代码块前面要加关键字synchronized(同步的意思),后面加一个锁对象(同步锁),把对象锁住

2同步方法

定义一个方法,方法使用synchronized修饰,这就是同步方法,保证A线程执行该方法的时候,其他线程只能在方法外面等着

格式:

public synchronized void mthod( ){

可能会产生线程安全问题的代码

}

同步方法的安全锁是谁?

对于非static方法,同步锁就是this(谁调用方法,谁就是this)

对于static方法,我们使用当前方法所在类的字节码对象(类名.class)

3Lock锁

Lock锁也叫同步锁,将加锁与释放锁方法话了,如下:

public void lock( ):加同步锁

public void unlock( ):释放同步锁

线程状态

导致状态发生条件

New(新建)

线程刚被创建,但是并未启动。还没调用start方法

Runnable(可运行)

线程可以在java虚拟机中运行,可能正在运行自己代码,也可能没有,这取决于操作系统处理器

Blocked(锁阻塞)

当一个线程试图获取一个对象锁,而该对象锁被其他线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程状态变成Runnable状态

Waiting(无限等待)

一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒

Timed Waiting(计时等待)

同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep和Object.wait

Teminated(被终止)

因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡

等待唤醒案例:线程之间的通信

创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,让自己放弃cpu的执行,进入到Waiting状态(无限等待)

创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子

注意:

1顾客和老板线程,必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行

2同步使用的锁对象,必须保证是唯一的

3只有锁对象才能调用wait和notify方法

Object类中的方法:

void wait():在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待

void notify():唤醒在此对象监视器上等待的单个单元。唤醒后会继续执行wait()方法之后的代码

线程池Executor

线程池了解即可

未来开发中,我们主动使用线程池会特别少,因为后续我们作为javaEE开发工程师,后端程序本身就是基于多线程的,已经有池缓存的概念了,就不需要我们再加线程池了

线程池的概述

线程一般经历以下四个阶段:创建线程->创建任务->执行任务->关闭线程

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间

线程池就是一个容纳多个线程的容器,池中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。

线程池的好处

1降低资源消耗

2提高相应速度

3提高线程的可管理性

Java中的四种线程池

1缓存线程池(非定长线程池)

2定长线程池

3单线程线程池(就一个线程)

4周期性任务定长线程池(定长线程池,它可以设置触发条件)

01缓存线程池

 

 02定长线程池

03单线程线程池

04周期任务定长线程池 

 

Lambda标准格式

Lambda省去面向对象的条条框框,格式由3个部分组成:

一些参数

一个箭头

一段代码

格式

(参数类型 参数名称) -> {代码语句}

格式说明

( ):接口中抽象方法的参数列表:无参数则留空;多个参数则用逗号分隔

->:是新引入的语法格式,代表指向动作,传递的意思把参数传递给方法体

{}:大括号内的语法与传统方法体要求基本一致,重写接口的抽象方法的方法体

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值