温故知新 线程

项目中常会用到定时器任务调度(线程知识)

本人原电子系后转行到软件,所以对计算机原理方面颇感兴趣!

 

 

谈线程钱必须知道进程,CPU调用程序,以进程体系,轮询。

 

时间片(CPU定轮询周期),每个进程周期一样,(如上图)当前执行进程1指令。执行到一半,操作系统OS (管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石给它分配时间到了,收回。

它把这个进程挂起,暂时保存起来。OS就去按顺序遍历,执行进程2,...........直到执行到进程8的时间片用完了,挂起进程8接着执行进程1,恢复现场,接着执行。

 

 

 

 

注意:进程调度,程序之间可以切换cpu执行太快会给人错觉误以为程序都是并行(同时运行);其实cpu定轮询周期(时间片),每个进程运行/执行的时间固定,当时间到了进程仍没执行完,当前进程挂起,执行下一条进程(直到进程8结束),当OS再次执行时,又回到进程1,恢复现场,接着执行;

知道了进程后,开始谈谈线程了:

一个进程可包含多个线程,也就是线程是OS(操作系统)可以执行的最小单位;(查服务器主机几核几线程  【cmd->wmic->cpu get *】查看对应的NumberOfCoresNumberOfLogicalProcessors

线程数=Ncpu/(1-阻塞系数)

Ncpu---CPU数     阻尼系数---(0到1之间)

线程数大于CPU核数(并行):

并行多核情况下各自CPU执行各自内容,可以同时执行;

并发多核情况下,某一个核中执行个线程,此时就产生并发,分片执行,轮着顺序执行。也称为交替执行。

上图摘自网络:(一图胜千文)

JVM在多线程时,访问公用变量(堆、方法区。。。)的每个线程是自由的,但有线程存在私有变量会有私有的栈来供他存放(保证了线程间隔离的安全)

 

切记创建线程数非常多,可能造成内存溢出;--------因为每个线程要分配单独内存空间,直接占用。(可以理解为独食大王,宁占着不让位)

 

多线程创建方式:

1) 继承Thread

2) 实现Runnable,无返回值,无异常接收

3) 实现Callable,返回值,接收异常,多了一些对象 FutureFutureTask

4) 线程池

 

 

多线程状态:

1,新建new;调用start()方法,注:所有的线程都从start开始(仅一次且由OS决定

2,可运行态Runnable; 1, 当时间片用完,运行态会调用 yiled()转到可运行态;注:【yiled() 会强制退回到就绪状态,代码主动调用。主动把CPU让出来,让其他线程去执行。俗称挂起   ,2,当OS选中时,会从可运行态转运行态;

3,运行态Running;Run方法执行完成,线程就结束,释放资源。(切记不要本线程调用---那将毫无意义)

4,阻塞态blocked;  对于阻塞态运行态可运行态 典型的稳定三角关系:

运行态变阻塞:

        sleep()   【它会把CPU让出来,先阻塞等待(我先睡会你们继续)】醒来后转为可运行态;

        join() 【运行快的所有线程都等待,只到最慢那个线程执行完成,(有福同享,有难共当)】   

        wait()   【当前线程优先占用,其他线程停止,(有肉我先吃)】 当调用interrupt()或notify()或notifyAll()被唤醒后仍处于阻塞态,可转为可运行态;’

        加锁Synchronized 【关键字,同步,同步锁,代码块,多行代码被加锁】 原子性操作,其他线程无法执行(特别注意CPU不是立即执行,而是轮询到它在执行。),切记加锁范围越小越好!

阻塞态变可运行态:获得锁   sleep时间到了

5,终止态Dead ;run()结束

 

特别要重视线程池:

通俗讲就是线程的集合,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。(可以理解为 孟尝君食客三千待用);

作用:防止多线程运行,系统不断闭合新线程,系统资源不断消耗,线程切换频繁,导致系统崩溃 (蓝屏的真好喝!)

线程池可参见博客大神闯天创世纪的博文:https://www.cnblogs.com/jiawen010/p/11855768.html

 

多线程并发在项目中常见安全问题:

甩卖问题:

多个窗口卖固定的货:      m个窗口   卖n件货

线程m个   甩卖过程   n递减(假设没退换,卖出责任不究)

其实主要是当n=1时问题出来了,要解决超卖现象:解决办法-------加锁(执行结束锁就释放),在加锁范围内不能高并发,只能一个对象去使用。

 

在商品秒杀系统时,有条件有选择的在读操作上加锁,库存小于一个量时开始加锁,让购买者排队;用一个队列缓存,将多线程变为单线程读写;

 

 

 

 

 

 

 

 

posted @ 2020-03-24 17:59  唯恐不及  阅读(131)  评论(0编辑  收藏  举报