Java多线程编程实战指南读书笔记三

线程数设置的原则 对于CPU密集型线程,考虑到这些线程执行任务值消耗的主要是处理器资源,我们可以将线程数设置为$N_{cpu}$,有事也可以设置为$N_{cpu}+1$ 对于I/O密集型线程,考虑到I/O操作可能导致上下文切换,为这样的线程设置过多的线程数会导致过多的额外系统开销,如果一个工作线程能够满足旧不需要设置更多的线程,如果一个工作者线程不够用,我们可以考虑将这类线程的数量设置为$2*N_{cpu}$ 等待与通知:wait/notify一个线程因为执行目标动作所需的保护条件未满足而被暂停的过程就被称为等待,一个线程更新了系统的状态,使得其它线程所需要的保护条件得以满足的时候唤醒那些被暂停的线程的过程被称为通知。 wait/notify的作用与用法Java平台中Object.wait()/Object.wait(long)和Object.notify()/Object.notifyAll()可用于实现等待和通知。

Java多线程编程实战指南读书笔记二

线程同步机制线程同步机制一套用于协调线程间的数据访问及活动的机制,该机制用于保障线程安全以及实现这些线程的共同目标。广义上讲,Java提供的线程同步机制包括,锁、volatile关键字、final关键字、static关键字以及一些相关的API。 锁线程安全产生的前提是多个线程并发访问共享变量、共享资源。使用锁保障线程安全的思路是将多个线程对共享数据的并发访问转换为串行访问。 使用锁保障线程安全的原理:一个线程在访问共享数据之前需要请求获得相应锁(锁的获得),一个锁同一时间只能被一个线程持有。只有持有锁的线程才能访问共享变量。在线程持有锁之后到释放锁这段时间所执行的代码被称为临界区。因此,共享数据只允许在临界区内进行访问,临界区一次只能被一个线程执行。 锁的性质:锁具有排他性,即一个锁一次只能被一个线程持有。因此这种锁被称为排他锁或者互斥锁。 锁的划分: 内部锁:通过synchronized关键字实现的 显式锁:通过java.concurrent.locks.Lock接口实现的。

Java多线程编程实战指南读书笔记一

进程、线程与任务什么是进程进程是程序运行的实例。运行一个java程序的实质是启动一个Java虚拟机进程,也就是说一个运行的Java程序就是一个Java虚拟机进程。进程是程序向操作系统申请资源的基本单位。 什么是线程线程是进程中可以独立执行的最小单位。一个进程可以包含多个线程。同一个进程中的所有线程共享该进程中的资源。 什么是任务线程所要完成的计算就被称为任务,特定的线程总是在执行着特定的任务。 Java线程API简介Thread类或其子类的一个实例就是一个线程。 线程的创建、启动和运行运行一个线程实际上就是让虚拟机运行该线程的run方法,从而使相应的线程任务处理逻辑代码得以执行。我们可以使用Thread类的start方法启动线程。当这个线程何时能够运行是由线程调度器决定的。因此调用了start方法,并不代表线程就立刻运行了。 以下是创建线程的几种方法:

Java NIO 学习笔记三

选择器基础选择器提供选择执行已经就绪的任务的能力。就绪选择和多元执行使得单线程能够有效率的同时管理多个I/O通道。 选择器:选择器管理着一个被注册的通道集合的信息和他们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。 可选择通道:这个抽象类提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。 选择键:选择键封装了特定的通道与特定的选择器的注册关系。 调用可选择通道的register()方法会将它注册到一个选择器上,但是这个通道必须是开启的并且处于非阻塞状态的。一个给定的通道可以注册到多于一个的选择器上。选择器是提供选择功能的对象,选择器对象对注册到它之上的通道进行就绪选择,并管理选择键。

Java NIO 学习笔记二

通道基础Channel表示IO源与目标打开的连接。在NIO中所有的IO都是从通道开始的。从通道进行数据的读取或者从通道进行数据写入。通道的顶层接口只Channel接口。其中定义了两个方法。 12public boolean isOpen()public void close() throws IOException; 由Channel引申的实现类都是面向ByteBuffer的。将IO从广义上分类,可以分为File I/O和Stream I/O。相应的也有两种不同类型的通道,分别是文件通道,和套接字通道。分别是FileChannel和SocketChannel、ServerSocketChannel、DatagramChannel. 通道可以是单向的也可以是双向的,这取决于它们对ReadableByteChannel接口和WritableByteChannel接口的实现情况。而ByteChannel做的工作仅仅是聚集接口。实现ByteChannel接口的通道可以是双向的。但它不一定就是双向的,比如从FileInputStream对象使用getChannel方法获取的FileChannel对象是只读的,这和权限有关。

Java NIO 学习笔记一

缓冲区操作进程执行I/O操作,归结起来就是向操作系统发出请求,它要么把缓存区例的数据排干(写),要么用数据把数据区填满(读)。进程使用这一机制处理所有数据进出操作。进程使用read()系统调用,要求其缓存区被填满。内核随即向磁盘控制器发出命令,要求其从磁盘读取数据。通过DMA技术直接将磁盘中的数据写入内核内存缓存区,一旦磁盘控制器把缓存区填满,内存立即把数据从内核空间的里你是缓冲区拷贝到进程执行read()调用时指定的缓冲区。 发散/汇聚根据发散/汇聚的概念,进程只需要一个系统调用,就能把一连串的缓冲区地址传递给操作系统。然后,内核就能顺序填充或排干多个缓冲区,读的时候将数据发散到多个用户空间缓冲区,写的时候再从多个缓冲区把数据汇聚起来。 利用虚拟内存避免一些拷贝前面提到设备控制器不能使用DMA直接存储到用户空间,需要从内核空间拷贝到用户空间。但在使用内存多重映射技术可以避免这种拷贝。现代操作系统都使用虚拟内存,它有极大优点: 多个虚拟地址可以映射到同一个物理地址。 虚拟内存空间可能大于实际可用的硬件内存。

大三上的学习计划

总的目标 这学期得把软件设计师给考过 六级成绩至少得提高吧 绩点要提高,课上讲得也很重要。利用周末做好总结。 减肥减到115斤,要注意健康管理了。 算法得每天练习,每天至少两道。 技术学习要抓紧了。 冬天到了不要起不来啊!!! 每个阶段的任务 九...

深入理解计算机系统读书笔记四

异常控制流(Exceptional Control Flow ,ECF)什么是控制流从给处理器加电开始,直到断电为止,程序计数器假设一个值的序列:a0,a1,a2…a n-1,其中a k是相应的指令的地址,每次从a k到a k-1的过渡称为控制转移(control transfer)。这样的控制转移序列称为处理器的控制流(flow of control)。 异常异常是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现。异常(Exception)就是控制流中的突变,用来响应处理器状态中的某些变化。在任何情况下,当处理器检测到有事件发生时,它就会通过一张叫做异常表(Exception Table)的跳转表,进行一个间接过程调用,到一个专门设计的用来处理这类事件的操作系统子程序(异常处理程序(exception handler))。当异常处理程序处理完成后,根据引起异常的事件类型,会发生以下3种情况种的一种。1.处理程序将控制返回当前指令2.处理程序将控制返回下一条3.处理程序终止被中断的程序

深入理解计算机系统读书笔记三

高速缓存的写操作假设缓存中已经缓存了字w(写命中)。在高速缓存更新了它的w的副本后,它有两种方式更新w在层次结构中紧接着低一层中的副本。 直写。就是立即将w的高速缓存块写回紧接着的低一层中。这种做法每次都会引起总线流量。 写回。写回会尽可能的推迟更新,只有当替换算法要驱逐这个更新过的块时,才会把他写道紧接着的第一层中。写回可以显著的减少总线流量,但是增加了复杂性。 假设缓存中没有缓存字w(写不命中),也有两种处理方式。1.写分配(write-allocate),加载相应的第一层中的块到高速缓存中,然后更新高速缓存块,试图利用写的空间局部性,但缺点是每次写不命中都会导致一个块从第一层传送到高速缓存。2.非写分配(not-write-allocate)。避开高速缓存,直接把这个字写到低一层中。 实际的高速缓存层次结构在实际中,高速缓存既保存数据,也保存指令。只保存指令的高速缓存被称为i-cache,只保存数据的高速缓存被称为d-cache。既保存指令又保存数据的高速缓存被称为统一的高速缓存(unifiied cache)。i-cache通常是只读的。

深入理解计算机系统读书笔记二

内存映射I/O技术CPU使用内存映射I/O技术来向I/O设备发射命令。在使用内存映射I/O的系统中,地址空间中有一块地址是为了与I/O设备通信保留的。每个这样的地址称为I/O端口。当一个设备连接到总线时,它被映射到一个或多个端口。通过内存映射I/O技术将I/O设备放置到内存空间而不是I/O空间,使得访问系统设备和访问内存一样,简化了程序设计的难度和接口的复杂性。 直接内存访问(DMA)设备可以字节执行读或写总线事务而不需要CPU干涉的过程,称为直接内存访问,这种数据传送被称为DMA传送。 为什么SSD随机写比随机读慢数据是以页为单位进行读写的。只有在一页所属的块整个被擦出后才能写。随机写的速度慢有两方面的原因。首先擦除块需要相对较长的时间,比访问页的的时间一般会高出一个数量级。另以方面,如果试图写的页所属的块中包含其它数据,就必须将块中带有数据的页复制到一个已经擦除的块中,然后再将块进行擦除然后写入数据页。显然,这会耗费很多时间。为了解决这个问题,制造商再内存翻译层中实现了复杂的逻辑,最小化内部写的次数,但是随即写的性能也很难与随机读一样好。