在日常的项目开发中,我们免不了会遇到高并发或者占用资源比较多的操作,此时使用多线程并发解决这些问题可以提高程序的运行性能。
1.线程的概念
下图显示了一个线程完整的生命周期。
2.线程安全
可参考:Synchronized和Lock和volatile对比_罗晓胜-CSDN博客_javasynchronized和volatile和lock
根本原因: 线程与线程之间相互独立 互不沟通 ----> 内存不可见,在Java中引入了锁的机制解决线程安全问题;
2.1Synchronized(同步锁)
采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。
synchronized修饰符可以修饰在对象、类、方法前。
2.2Lock
和synchronized不同的是,Lock是一个接口,需要用户自己手动释放锁。
2.3volatile
volatile是一种稍弱的同步机制,在访问volatile变量时不会执行加锁操作,也就不会执行线程阻塞,因此volatilei变量是一种比synchronized关键字更轻量级的同步机制。
3.线程池实现多线程
在阿里的java开发规约中,我们可以看到以下内容:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,
这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
因此在项目中,我们在创建线程时都要通过线程池来创建。
3.1单例模式
3.1.1饿汉模式
饿汉模式顾名思义,就是单例模式的对象在调用之前就已经创建完成,步骤为:
1. 构造方法私有化
2. 提供一个静态方法
3. 饿汉模式: 需要提供静态变量 直接实例化
public class Student {
//1.构造方法私有化
private Student() {
}
//2. 提供一个静态方法
//3. 饿汉模式: 需要提供静态变量 直接实例化
//static 的内容 只被加载1次
private static Student student = new Student();
public static Student getInstance() {
return student;
}
}
饿汉模式 不存在线程安全的问题
3.2.2懒汉模式
懒汉模式顾名思义,就是在调用对象时才创建对象,步骤为:
1. 构造方法私有化
2. 提供一个静态方法
3. 声明静态变量
public class UserInfo {
private UserInfo() {
}
private static UserInfo userInfo;//声明静态的变量 体现了懒加载的思想
public static UserInfo getInstance() {
if (userInfo == null) {
userInfo = new UserInfo();
}
return userInfo;
}
public static void a() {
}
}
懒汉模式可能出现线程安全问题,比如当多个线程不设锁时,可能会实例化多个对象。
3.2线程池
3.2.1线程池原理
3.2.2单例模式创建线程池(双重检测锁)
在实际创建线程池时,我们可以同时使用懒汉模式和饿汉模式的思想,我们首先需要有线程池管理类 AsycThreadPoolManager,然后使用ThreadPoolExecutor创建线程池,在声明这二者之后我们加volatile修饰符,这是第一重锁。
ThreadPoolExecutor采用饿汉模式,我们可以写一个静态代码块来编写实例化对象;
AsycThreadPoolManager采用懒汉模式,在声明后在获取自己对象的方法中再进行实例化,但实例化过程中需要使用synchronized进行上锁,避免出现线程安全问题,这是第二个锁。
最后写executeTask方法,从池子里面获得一个闲置的线程对象执行任务,所传参数为Runnable.
具体代码:
package com.Gavin.common;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author: Gavin
* @description:
* @className: AsycThreadPoolManager
* @date: 2022/3/4 9:31
* @version:0.1
* @since: jdk14.0
*/
//单例模式(懒汉)
public class AsycThreadPoolManager {
private volatile static ThreadPoolExecutor threadPoolExecutor; //线程池
private volatile static AsycThreadPoolManager threadPoolManager;
static {
threadPoolExecutor=new ThreadPoolExecutor(10,
50,10,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(30),new ThreadPoolExecutor.CallerRunsPolicy());
}
//单例模式
public static AsycThreadPoolManager getInstance(){
if (threadPoolManager==null){
synchronized (AsycThreadPoolManager.class){ //同步锁 防止多线程出现多个实例
if(threadPoolManager==null){
threadPoolManager=new AsycThreadPoolManager();
}
}
}
return threadPoolManager;
}
public void executeTask(Runnable task){
//从池子里面获得一个闲置的线程对象执行任务
threadPoolExecutor.execute(task);
}
}