高并发初级

1.线程

1.1 进程和线程

1.1.1进程由程序段、数据段和进程控制块三部分组成

在这里插入图片描述

1.1.2线程是由线程描述信息、程序计数器和栈内存组成

在这里插入图片描述
线程描述信息主要包括:
1)线程ID
2)线程名称
3)线程优先级
4)线程状态
5)其他,如守护线程等
栈内存是线程独立拥有,各线程之间不共享.栈内存不受垃圾回收器管理.

1.1.3总结

1)一个进程至少有一个线程,线程是进程的最小执行单元,火车与车厢的关系
2)进程是操作系统分配的最小单位,线程是cpu调度的最小单位
3)进程之间相互独立,线程之间并不完成独立,各个线程共享堆内存和系统资源

1.2 创建线程的4中方式

在这里插入图片描述
包括线程id,线程名称,线程优先级,是否守护线程,线程状态,线程的启动和运行,获取当前线程,其他属性等

1.2.1继承Thread类

1)继承Thread类,创建一个新的线程类
2)重写run()方法,将业务代码放到run()里

1.2.2实现Runnable接口创建线程目标类

Thread有两个构造器
1)public Thread(Runnable target)
2)public Thread(Runnable target,String name)
Runnable接口很简单,在java.lang包中.接口中只有且仅有一个抽象run()方法
package java.lang
@FunctionaInterface //定义函数式接口的注解
public interface Runnable{
void run();
}
实现方式:
1)定义一个新类实现Runnable接口
2)重写run()方法,将业务代码放到run()里
3)通过Thread类创建线程对象,将Runnable实例作为实际参数传给Thread构造器,由Thread构造器将该Runnable实例赋值给自己的target执行目标属性
4)调用Thread实例的start()方法
Lambda表达式优雅的写法:
Thread thread=null;
thread =new Thread (() ->{
//代码逻辑
},“threadName”);
thread.start();
区别:
1)通过继承Thread类,可以做到多个线程并发执行各自的任务
2)通过实现Runnable可以做到多个线程并发的完成同一个任务,访问同一份数据资源
3)通过实现Runnable时,数据资源共享时要用原子类型(不是普通类型) //AtomicInteger

1.2.3实现Callable接口

FutureTask类实现了RunnableFuture接口,RunnableFuture实现了future接口,可以有返回值,也实现了Runnable接口,可以作为Thread的实例参数,特点就是有返回值
实现方式:
1)创建一个Callable接口的实现类,并实现call方法,写好业务方法,可以有返回值
2)使用Callable实现类的实例构造一个FutureTask实例
3)使用FutureTask实例作为Thread构造器的参数入参,构造新的Thread线程实例
4)调用Thread实例的start()方法启动新线程
5)调用FutureTask对象的get()方法阻塞性地获得并发线程的执行结果

1.2.4通过线程池创建线程

通过Executors工厂类创建一个线程池,Executors是java提供的一个线程池接口
private static ExecutorService pool = Executors.newFixedThreadPool(3);
实现方式:
1)执行一个Runnable类型的target执行目标实例,无返回
void execute (Runnable command);
2)提交一个Callable类型的target执行目标实例,返回一个Future异步任务实例
Future submit (Callable task);
3)提交一个Runnable类型的执行目标实例,返回一个Future异步任务实例
Future <?> submit (Runnable task);
executor和submit的区别:
1)接收参数不同
2)submit有返回值,execute无返回值

1.3线程的优先级

public final int getPriority();
public final void setPriority();
默认级别为5,最小为1,最大为10.优先级为1~10,越来越高,但并不绝对
特性:
1)整体而言,高优先级的线程获得的执行机会会更多
2)执行机会的获取具有随机性,优先级高的不一定获得的机会多.

1.4线程的生命周期

1)New状态
2)Runnable状态 :调用了start()方法,未执行,或者获取cpu开始执行
3)Blocked阻塞状态
4)Waiting等待状态
5)Timed_waiting限时等待状态:例如:Thread.sleep();
Thread.join(); t2.join()则t2线程执行完后本线程才执行.
Object.wait();
LocksSupport.parkNanos();让线程等待,时间以纳秒为单位
LocksSupport.parkUntil();让线程等待,时间灵活设置

1.5使用Jstack工具查看线程状态

命令:jstack
输出内容
1)tid:线程实例在jvm中的id
2)nid:线程实例在操作系统中多赢的底层线程的线程id
3)prio:线程实例在jvm进程中的优先级
4)0s_prio:线程实例在操作系统中对应线程的优先级
5)线程状态:runnable/waiting等
6)Terminated终止状态 run方法执行完

1.6线程的基本操作

1.6.1 线程名称的设置和获取

1)线程名称一般在启动前设置,但也允许运行的线程设置
2)运行两个Thread有两个相同的名称,但应避免
3)如果程序没有指定线程名称,系统会自动设置名称

1.6.2线程的sleep操作

1)会用InterruptException受检异常抛出
2)属于Thread类
3)不会释放机锁

1.6.3线程的interrupt操作

1)如果此线程处于阻塞状态,会立马退出阻塞,并抛出interruptExpection异常,线程可以捕获异常并做处理
2)处于正在运行中的线程不受影响,但线程的中断状态会为true.可以通过监视线程的isInterrupted()状态,进行相应的处理.

1.6.4 线程的join操作

1)join()方法有三个重载方法 无参 一参 两参
2)需要被合并的先执行线程变量调用 t2.join
3)t2.join(1000mills) ,并不能保证当前线程一定会在mills时间后变成RUNNABLE状态
4)如果主动方合并线程在等待时被中断,就会抛出interruptedExpection异常
在这里插入图片描述

1.6.5线程的yield操作

1)yeild让步
2)yeild仅能使一个线程从运行状态转到就绪状态,而不是阻塞状态
3)不能保证当前线程迅速转为就绪状态

1.6.6线程的daemon操作

1)一个实例属性和两个实例方法定义守护线程
2)实例属性daemon: private boolean daemon = false;
3)实例方法setDaemon(true) :守护线程 ,setDaemon(false) :用户线程
4)实例方法isDaemon():获取线程的守护状态,用于判断
5)必须在线程启动前设置守护状态,否则jvm会抛出InterruptedException异常
6)守护线程创建的线程也是守护线程

1.6.7线程状态总结

1)NEW状态:
new Thread(…)创建线程,但未调用start()
2)RUNNABLE状态:
-调用线程的start()方法
-当前线程的执行时间片用完
-线程睡眠Sleep结束
-对其他线程合入Join结束
-等待用户输入结束
-线程争抢到对象锁
-当前线程调用了yeild()方法出让CPU执行权限
3)BLOCKED状态
-线程等待获取锁
-IO阻塞
4)WAITING状态
-Object.wait() 唤醒方式Object.notify()/Object.notifyAll()
-Thread.join() 唤醒方式,被合入的线程执行完毕
-Locksupport.park() 唤醒方式 Locksupport.unpark()
5)TIMED_WAITING状态
-Thread.sleep(time) 唤醒方式,睡眠时间结束
-Object.wait() 唤醒方式Object.notify()/Object.notifyAll()
-Locksupport.parkNanos(time)/parkUntil(time) 唤醒方式 Locksupport.unpark()

注意:
BLOCKED,WAITING,TIMED_WAITING状态的线程都会让出CPU的使用权;另外,等待或者阻塞状态的线程被唤醒后,进入Ready状态,需要重新获取时间片才能接着运行.
6)TERMINATED状态
-线程结束/异常没有处理

1.7线程池

作用:
提升性能
线程管理
减小开销

1.7.1JUC的线程池架构

1)Executor是java异步目标任务的执行者接口
2)ExecutorService
3)AbstractExecutorService
4)ThreadPoolExecutor
5)ScheduledExecutorService
6)ScheduledThreadPoolExecutor
7)Executors静态工厂类,提供创建线程池方法

1.7.2Executors的4中创建线程池的方法

1)newSingleThreadExecutor() 单个线程池
适合:任务按照提交次序,一个任务一个任务的逐个执行的场景
2)newFixedThreadPool(int n) 固定数量线程池
适合:任务长期执行,线程数保持稳定的一个数
3)newCacheThreadPool() 可缓存线程池
适合:快速处理突发性强,耗时较短的场景,如Netty的NIO处理场景,线程数量不固定.弊端:线程池没有数量限制,大量任务易导致资源耗尽
4)newScheduledThreadPool(int corePoolSize) 可调度线程池
适合:周期执行的任务场景

1.7.3线程池的标准创建方式

//使用标准构造器创造一个普通的线程池
public ThreadPoolExecutor(
int corePoolSize,//核心线程数,即使线程空闲(Idle),也不会回收
int maximumpoolSize,//最大线程数
long keepAliveTime,//空闲线程的存活时间
TimeUnit unit,//时长
BlockingQueue workQueue,//任务的排队队列
ThreadFactory threadFactory,//线程的产生方式
RejecteExecutionHandler handler//拒绝策略
)

1.7.4向线程池提交任务的两种方式

1)execute() 参数只能是Runnable 无返回值
2)submit() 蚕食可以使Runnable 也可以是Callable 有返回值 方便Exception处理

1.7.5线程池的任务调度流程

在这里插入图片描述

1.7.6ThreadFactory线程工厂

Executors为线程池的工厂类,ThreadFactory为线程的工厂类.
在调用ThreadFactory的唯一方法newThread()创建新线程是,可以更改所创建的新线程的名称,线程组,优先级,守护线程状态德国.如果newThread()返回null表示未成功.

1.7.7任务阻塞队列

特点:阻塞队列为空时会阻塞当前线程的元素获取操作
1)ArrayBlockingQueue
2)LinkedBlockingQueue
3)PriorityBlockingQueue
4)DelayQueue
5)SynchronousQueue

1.7.8调度器的钩子方法

1)beforeExecute:异步任务执行前的钩子方法
2)afterExecute:异步任务执行之后的钩子方法
3)terminated:线程池终止时的钩子方法

1.7.9线程池的拒绝策略

1)线程池已经被关闭
2)工作队列已满且maximumPoolSize已满
以上任一,线程池都会调用RejectedExecutionHandler实例的rejectedExecution方法

1.7.10线程池的优雅关闭

线程池的5种状态
1)running:初始状态,可执行
2)shutdown:线程池不会接受新任务
3)stop:不会接受新任务,且不会处理工作队列中的剩余任务,中断所有
4)tidying:所有任务都已终止,执行terminated()钩子函数
5)terminated:执行terminated()钩子方法后的状态
优雅关闭:
1)执行shutdown()
2)执行awaitTermination(long timeout,TimeUnit unit),判断任务是否都关闭
3)如果awaitTermination(long timeout,TimeUnit unit)返回false,或者被中断,就调用shutdownNow()方法关闭所有任务
4)补充执行awaitTermination(long timeout,TimeUnit unit)方法,如果超时就循环 (1000次),直到循环结束

1.8ThreadLocal原理与实战

线程本地变量,是线程具有独立性,内部是一个map,主要通过ThreadLocalMap实现
使用场景:
1)线程隔离
2)跨函数传递数据
方法:
set(value) ,get(),remove(),initialvalue(0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值