图灵课堂java互联网架构师怎么样?

关键词:图灵学院java架构师VIP

共找到 800“图灵学院java架构师VIP”相关课程

  • 免费 4881人最近报名

  • 免费 593人最近报名

  • 免费 509人最近报名

  • 免费 923人最近报名

腾讯课堂为您提供高质量的图灵学院java架构师VIP在线课程,图灵学院java架构师VIP培训视频教程内容来源于入驻腾讯课堂的优秀教育机构和老师提供的。了解更多培训班、学图灵学院java架构师VIP课程,就上腾讯课堂

}

0 22:21:00未经作者授权,禁止转载

Java高级架构交流QQ群: 备注(B站) 领取最新Java面试资料和Java架构学习资料! 欢迎大家学习打卡,互相鼓励互相加油! 更多学习、面试资料、源码资料分享!

}

学并发编程不先了解操作系统总有些雾里看花的感觉。

计算机五大核心组成部分:

  1. 控制器(Control):是整个计算机的中枢神经,其功能是对程序规定的控制信息进行解 释,根据其要求进行控制,调度程序、数据、地址,协调计算机各部分工作及内存与外设的访 问等。
  2. 运算器(Datapath):运算器的功能是对数据进行各种算术运算和逻辑运算,即对数据进 行加工处理。
  3. 存储器(Memory):存储器的功能是存储程序、数据和各种信号、命令等信息,并在需 要时提供这些信息。
  4. 输入(Input system):输入设备是计算机的重要组成部分,输入设备与输出设备合你为 外部设备,简称外设,输入设备的作用是将程序、原始数据、文字、字符、控制命令或现场采 集的数据等信息输入到计算机。常见的输入设备有键盘、鼠标器、光电输入机、磁带机、磁盘 机、光盘机等。
  5. 输出(Output system):输出设备与输入设备同样是计算机的重要组成部分,它把外算 机的中间结果或最后结果、机内的各种数据符号及文字或各种控制信号等信息输出出来。微机 常用的输出设备有显示终端CRT、打印机、激光印字机、绘图仪及磁带、光盘机等。

CPU多核:一个现代CPU除了处理器核心之外还包括寄存器、L1L2L3缓存这些存储设备、浮点运算 单元、整数运算单元等一些辅助运算设备以及内部总线等。一个多核的CPU也就是一个CPU上 有多个处理器核心,这样有什么好处呢?比如说现在我们要在一台计算机上跑一个多线程的程 序,因为是一个进程里的线程,所以需要一些共享一些存储变量,如果这台计算机都是单核单 线程CPU的话,就意味着这个程序的不同线程需要经常在CPU之间的外部总线上通信,同时还 要处理不同CPU之间不同缓存导致数据不一致的问题,所以在这种场景下多核单CPU的架构就 能发挥很大的优势,通信都在内部总线,共用同一个L2L3缓存,L1为独有。

新的(NEW):进程正在被创建
运行(RUNNING):指令正在被执行
等待(WAIT):进程等待某个事件的发生(如I/O完成或受到信号)
就绪 (READY):进程等待分配处理器
终止(TERMINAL):进程完成执行

  • 空->新建:创建执行一个程序的新进程,可能的事件有:新的批处理作业、交互登录(终端用户登录到系统)、操作系统因为提供一项服务而创建、由现有的进程派生等。
  • 新建->就绪:操作系统准备好再接纳一个进程时,把一个进程从新建态转换为就绪态。(start)
  • 就绪->运行:需要选择一个新进程运行时,操作系统的调度器或分配器根据某种调度算法选择一个处于就绪态的进程。
  • 运行->退出:导致进程终止的原因有:正常完成、超过时限、系统无法满足进程需要的内存空间、进程试图访问不允许访问的内存单元(越界)、算术错误(如除以0或存储大于硬件可以接纳的数字)、父进程终止(操作系统可能会自动终止该进程所有的后代进程)、父进程请求终止后代进程等。
  • 运行->就绪:最常见的原因是,正在运行的进程到达了“允许不中断执行”的最大时间段,该把处理器的资源释放给其他在就绪态的进程使用了;还有一中原因可能是由于具有更改优先级的就绪态进程抢占了该进程的资源,使其被中断转换到就绪态。
  • 运行->阻塞:如果进程请求它必须等待的某些事件,例如一个无法立即得到的资源(如I/O操作),只有在获得等待的资源后才能继续进程的执行,则进入等待态(阻塞态)。
  • 阻塞->就绪:当等待的事件发生时,处于阻塞态的进程转换到就绪态。
  • 就绪->退出:在上图中没有标出这种转换,在某些进程中,父进程可以在任何时刻终止一个子进程,如果一个父进程终止,所有相关的子进程都被终止。
  • 阻塞->退出:跟上一项原因类似。

进程控制块(PCB):作为信息仓库,进程与进程间不同

  • 进程状态(Process state): 状态可包括新的,就绪,运行,等待,终止等。
  • 程序计数器(Program counter) : 计数器表示进程要执行的下个指令的地址。
  • CPU寄存器(CPU registers):与程序计数器一起,这些寄存器的状态信息在出现中断时也需要保存,以便进程以后能正确的执行。
  • CPU调度信息(CPU scheduling information):这类信息包括进程优先级、调度队列指针和其他调度参数。
  • 内存管理信息(Memory-management information):根据内存系统,这类信息包括基址和界限寄存器的值,页表或段表。
  • 记账信息(Accounting information):这类信息包括CPU时间、实际使用时间、时间界限、记账数据、作业或进程数量等。
  • I/O状态信息(I/O status information):这类信息包含分配给进程的I/O设备列表、打开的文件列表等。

进程进入系统时,会被加入到作业队列中,该队列包含系统中所有进程。驻留在内存中就绪的、等待运行的程序保存在就绪队列中。该队列常用链表来实现,其头节点指向链表的第一个和最后一个PCB块的指针。每个PCB包括一个指向就绪队列的下一个PCB的指针域。
进程会在各种调度队列之间迁移,为了调度,操作系统必须按某种方式从这些队列中选择进程
将CPU切换到另一进程需要保存当前状态并恢复另一进程状态
通常进程需要一定的资源(如CPU时间,内存,文件,I/O设备)来完成其任务。子进程被创建时,子进程可能直接从操作系统,也可能只从父进程那里获取资源。父进程可能必须在其子进程之间分配资源或共享资源(如内存或文件),限制子进程只能使用父进程的资源能防止创建过多的进程带来的系统超载。
UNIX:可以通过系统调用exit()来终止进程,父进程可以通过系统调用wait()以等待子进程的终止。系统调用wait()返回了中止子进程的进程标识符,以使父进程能够知道哪个子进程终止了。如果父进程终止,那么其所有子进程会以init进程作为父进程,因此,子进程仍然有一个父进程来收集状态和执行统计。

  • 进程共享内存:共享内存系统需要建立共享内存区域。通常一块共享内存区域驻留在生成共享内存段进程的地址空间。其他希望使用这个共享内存段进行通信的进程必须将此放到它们自己的地址空间上。数据的形式或位置取决于这些进程而不是操作系统,进程还负责保证他们不向同一区域同时写数据
  • 消息传递系统:消息传递提供一种机制以允许进程不必通过共享地址空间来实现通信和同步,这在分布式系统中很有用。例如用于WWW的chat程序就是通过信息交换来实现通信。

RMI和RPC之间区别:在RMI中,远程接口使每个远程方法都具有方法签名。如果一个方法在服务器上执行, 但是没有相匹配的签名被添加到这个远程接口上,那么这个新方法就不能被RMI客户方所调用。在RPC中,当一个请求到达RPC服务器时,这个请求就包含了 一个参数集和一个文本值,通常形成“classname.methodname”的形式。这就向RPC服务器表明,被请求的方法在为 “classname”的类中,名叫“methodname”。然后RPC服务器就去搜索与之相匹配的类和方法,并把它作为那种方法参数类型的输入。这里 的参数类型是与RPC请求中的类型是匹配的。一旦匹配成功,这个方法就被调用了,其结果被编码后返回客户方

一种CPU利用的基本单元,它是形成多线程计算机的基础。线程是CPU使用的基本单元,它由线程ID、程序计数器、寄存器集合和栈组成。它与属于统一进程的其他线程共享代码段、_数据段和其他操作系统资源

  • 响应度高(Responsiveness):即使其部分阻塞或执行较冗长操作,该程序仍能继续执行,从而增加了对用户的相应程度。
  • 资源共享(Resource Sharing):线程默认共享它们所属进程的内存和资源。代码和数据共享的优点是它允许一个应用程序在同一地址空间有多个不同的活动线程。
  • 经济(Economy):进程创建所需要的内存和资源的分配比较昂贵。由于线程能共享它们所属进程的资源,所以创建和切换线程会更为经济。进程创建比线程慢30呗,切换比线程慢5倍。
  • 多处理器体系结构的利用(Utilization of MP Architectures):多线程的优点之一是能充分使用多处理器体系结构。以便每个进程能并行运行在不同的处理器上。不管有多少CPU,单线程进程只能运行在一个CPU上,在多CPU上使用多线程加强了并发功能。

创建状态(New)、就绪状态(Runnable)、运行状态(Running)、阻塞状态(Blocked)、死亡状态(Dead)

    1.线程休眠会交出CPU,让CPU去执行其他的任务。
    2.调用sleep()方法让线程进入休眠状态后,sleep()方法并不会释放锁,即当前线程持有某个对象锁时,即使调用sleep()方法其他线程也无法访问这个对象。
    3.调用sleep()方法让线程从运行状态转换为阻塞状态;sleep()方法调用结束后,线程从阻塞状态转换为可执行状态。 1.调用yield()方法让当前线程交出CPU权限,让CPU去执行其他线程。
    2.yield()方法和sleep()方法类似,不会释放锁,但yield()方法不能控制具体交出CPU的时间。
    3.yield()方法只能让拥有相同优先级的线程获取CPU执行的机会。
    4.使用yield()方法不会让线程进入阻塞状态,而是让线程从运行状态转换为就绪状态,只需要等待重新获取CPU执行的机会。
  • join()方法:指的是如果在主线程中调用该方法时就会让主线程休眠,让调用join()方法的线程先执行完毕后再开始执行主线程。
  • wait()方法:使用前必须先获得对象锁(通过synchronized)。释放锁并阻塞。
  • notify()方法:随机通知一个阻塞的线程,竞争获取锁。
  • notifyAll()方法:通知等所有阻塞的线程,竞争获取锁。

UNIX系统有两种形式的fork(),一种复制所有线程,另一种只复制调用了系统调用fork()的线程。
Exec()工作方式:如果一个线程调用系统调用exec(),那么exec()参数所指定的程序会替换整个进程,包括所有线程。
二是延迟取消(deferred cancellation):目标线程不断地检查它是否应终止,这允许目标线程有机会以有序方式来终止自己。
如果资源已经分配給要取消的线程,或者要取消的线程正在更新与其他线程所共享的数据,那么取消会有困难,对于异步取消尤为麻烦。操作系统回收取消线程的系统资源,但是通常不回收所有资源。因此,异步取消线程并不会使所需的系统资源空闲。相反采用延迟取消时,允许一个线程检查它是否是在安全的点被取消,pthread称这些点为取消点(cancellation point)

多线程环境下存在的问题

多个处理器的运算任务都涉及同一 块主内存区域时,由于每个CUP都有自己L1缓存,会导致缓存数据不一致,自然会产生错误结果回写到内存。

创建线程方法四种方法:

  • 继承Thread类创建线程
  • 使用线程池例如用Executor框架

主要用来创建线程池,代理了线程池的创建,使得你的创建入口参数变得简单 重要方法
newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool: 创建一个定长线程池,可控制线程最大并发线程会在队列中等待。 newScheduledThreadPool: 创建一个定长线程池,支持定时及周期行。

用于实现“分而治之”的算法,特别是分治之后递归调用的函数。不但可以加快速度也可以防止由于递归导致堆栈溢出。

  • ForkJoinTask: 它是将在ForkJoinPool中执行的任务的基类。它提供在任务中执行fork()和join()操作的机制,并且这两个方法控制任务的状态。通常, 为了实现你的Fork/Join任务,你将实现两个子类的子类的类:RecursiveAction对于没有返回结果的任务和RecursiveTask 对于返回结果的任务。

Unsafe提供的API大致可分为内存操作、CAS、Class相关、对象操作、线程调度、系统信息获取、内存屏障、数组操作等几类。

Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:

  • 普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
  • 静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
  • 同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

锁消除:是发生在编译器级别的一种锁优化方式,如多次调用一个加synchronized的方法,会被优化为一个,如StringBuffer
锁粗化:锁粗化是合并使用相同锁对象的相邻同步块的过程。如果编译器不能使用锁省略(Lock Elision)消除锁,那么可以使用锁粗化来减少开销。

特性:阻塞等待队列、共享(emaphore/CountDownLatch)/独占(ReentrantLock)、公平/非公平、可重入、允许中断。state高16位表示读锁状态(读锁个数),低16位表示写锁状态(写锁个数)。
基于双向链表数据结构的队列,是FIFO先入先出线程等待队列。
Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备时 ,这些等待线程才会被唤醒,从而重新争夺锁
1.同步队列是有头结点的,而条件队列没有(node.prev == null)
4.tail同步队列尾结点
CANCELLED(1) : 该节点的线程可能由于超时或被中断而处于被取消(作废)状态,一旦处于这个状态,节点状态将一直 处于CANCELLED,因此应该从队列中移除
SIGNAL(-1):表示该节点处于等待唤醒状态,后继节点会被挂起,因此在当前节点释放锁或被取消之后必须唤醒其后继结点
CONDITION(-2):该节点的线程处于等待条件状态,不会被当作是同步队列上的节点,直到被唤醒(signal),设置其值为0,重新进入阻塞状态
PROPAGATE(-3) - 下一个 acquireShared 应无条件传播。表示下一次共享式同步状态获取将会被无条件地传播下去

lock():默认非公平锁,lock(true)为公平锁有个等待队列
unlock():会释放锁,并且唤醒同步队列中线程
构造ArrayBlockingQueue时需要指定容量,也就意味着底层数组一旦创建了,容量就不能改变了,因此ArrayBlockingQueue是一个容量限制的阻塞队列。因此,在队列全满时执行入队将会阻塞,在队列为空时出队同样将会阻塞。

  • 一个对象数组+一把锁+两个条件
  • 入队与出队都用同一把锁,操作已经足够轻巧,不用引入多把锁。
  • 在只有入队高并发或出队高并发的情况下,因为操作数组,且不需要扩容,插入或删除元素时不会产生或销毁任何额外的对象实例,性能很高
  • 采用了数组,必须指定大小,即容量有限

维持两把锁,一把锁用于入队,一把锁用于出队,这也就意味着,同一时刻,只能有一个线程执行入队,其余执行入队的线程将会被阻塞;同时,可以有另一个线程执行出队,其余执行出队的线程将会被阻塞。换句话说,虽然入队和出队两个操作同时均只能有一个线程操作,但是可以一个入队线程和一个出队线程共同执行,也就意味着可能同时有两个线程在操作队列,那么为了维持线程安全,LinkedBlockingQueue使用一个AtomicInterger类型的变量表示当前队列中含有的元素个数,所以可以确保两个线程之间操作底层队列是线程安全的。

  • 一个单向链表+两把锁+两个条件
  • 两把锁,一把用于入队,一把用于出队,有效的避免了入队与出队时使用一把锁带来的竞争。
  • 在入队与出队都高并发的情况下,性能比ArrayBlockingQueue高,生成一个额外的Node对象。其对于GC有一定影响
  • 采用了链表,最大容量为整数最大值,可看做容量无限,如果不设置大小,生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了

基于优先级的阻塞队列(优先级的判断通过构造函数传入的Compator对象来决定),但需要注意的是PriorityBlockingQueue并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。因此使用的时候要特别注意,生产者生产数据的速度绝对不能快于消费者消费数据的速度,否则时间一长,会最终耗尽所有的可用堆内存空间。内部控制线程同步的锁采用的是公平锁。
DelayQueue 由优先级堆支持的、基于时间的调度队列
元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue是一个没有大小限制的队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。

  • DelayQueue使用场景较少,但都相当巧妙,常见的例子比如使用一个DelayQueue来管理一个超时未响应的连接队列。

SynchronousQueue 是一个特殊的队列,它的内部同时只能够容纳单个元素。如果该队列已有一元素的话,试图向队列中插入一个新元素的线程将会阻塞,直到另一个线程将该元素从队列中抽走。同样,如果该队列为空,试图向队列中抽取一个元素的线程将会阻塞,直到另一个线程向队列中插入了一条新的元素。

  • 如果采用公平模式:SynchronousQueue会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;
  • 如果是非公平模式(SynchronousQueue默认):SynchronousQueue采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。

BlockingDeque 一个双端队列,在不能够插入元素时,它将阻塞住试图插入元素的线程;在不能够抽取元素时,它将阻塞住试图抽取的线程,可以从任意一端插入或者抽取元素的队列。
LinkedBlockingDeque:一个基于已链接节点的、任选范围的阻塞双端队列。
可选的容量范围构造方法参数是一种防止过度膨胀的方式。如果未指定容量,那么容量将等于 Integer.MAX_VALUE。只要插入元素不会使双端队列超出容量,每次插入后都将动态地创建链接节点。
控制访问特定资源的线程数目

  • permits 表示许可线程的数量
  • fair 表示公平性,如果这个设为 true 的话,下次执行的线程会是等待最久的线 程

这个类能够使一个线程等待其他线程完成各自的工作后再执行。例 如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
await():主线程进入等待队列,当state不为0主线程进入阻塞状态。

栅栏屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程 到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
await():sate减1,线程加入条件等待队列并挂起。
当计数为0,lock.newCondition().singnalAll()唤醒所有条件队列的节点转移到同步队列当中。同步队列中所有线程都会执行ReentrantLock.unlock(),唤醒同步队列中的一个线程,最后所有任务执行完毕。

}

我要回帖

更多关于 图灵编程怎么样 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信