在线程中执行任务 当围绕”任务执行”来设计应用程序结构时,第一步就是要找出清晰的任务边界。 大多数服务器应用程序都提供了一种自然的任务边界选择方式:以独立的客户请求为边界。 串行地执行任务 在单个线程中串行地执行各项任务。大多数GUI框架都是通过单一的线程来串行地处理任务。 ...
Read More什么是内存模型,为什么需要它 平台的内存模型 为了使Java开发人员无须关系不同架构上内存模型之间的差异,Java还提供了自己的内存模型,并且JVM通过在适当的位置上插入内存栅栏来屏蔽JMM与底层平台内存模型之间的差异。 重排序 如果没有同步,那么推断处执行顺序将是非常困难的,而要确保在...
Read More锁的劣势 如果在基于锁的类中包含有细粒度的操作(例如同步容器类,在其大多数方法中只包含了少量操作),那么在当锁上存在着激烈的竞争时,调度开销与工作开销的比值会非常高。 当一个线程正在等待锁时,它不能做任何其他事情。如果被阻塞线程的优先级较高,而持有锁的线程优先级较低,就会产生 “优先级反转” 。即使高优先级的线程可以抢先执行,但仍然需要等待锁被释放,从而导致它的优先级会将至低优先级线程的级别。 与锁相比,volatile变量是一种更轻量级的同步机制,因为在使用这些变量时不会发生上下文切换货线程调度等操作。然而,volatile变量同...
Read MoreLock与ReentrantLock Lock提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显示的。 public interface Lock{ void lock(); void lockInterruptibly() throws InterruptedExceptedException; boolean tryLock(); boolean tryLock(long timeout,TimeUnit unit) throws I...
Read More在任务与执行策咯之间的隐性耦合 需要明确指定执行策咯的任务: 依赖性任务 大多数行为正确的任务都是独立的:它们不依赖于其他任务的执行时序、执行结果或其他效果. 使用线程封闭机制的任务 单线程的Executor能确保任务不会并发地执行,使你能够放宽代码对线程安全的要求. 对响应时间敏感的任务 如果将一个运行时间较长的任务提交到单线程的Executor中,或者将多个运行时...
Read More状态依赖性的管理 在并发程序中,基于状态的条件可能会由于其他线程的操作而改变:一个资源池可能在几条指令之前还是空的,但现在却变为非空的,因为另一个线程可能会返回一个元素到资源池。依赖状态的操作可以一直阻塞直到可以继续执行,这比使它们先失败再实现起来要更为方便且更不易出错。 有界缓存提供的put和take操作中都包含有一个前提条件:不能从空缓存中获取元素,也不能将元素放入已满的缓存中。当前提条件未满足时,依赖状态的操作可以抛出一个异常或返回一个错误状态(使其成为调用者的一个问题),也可以保持阻塞直到对象进入正确的状态。 有界缓存的几种实现: 每种实现...
Read More并发测试大致分飞两类: 安全性测试: 不发生任何错误的行为 活跃性测试: 某个良好的行为终究会发生 进展测试 无进展测试 性能通过多个方面来衡量: 吞吐量:指一组并发任务中已经完成任务所占的比例。 响应性:指请求从发出到完成之间的时间(也称为延迟)。 可伸缩性:指在增加更多资源的情况下(通常指CPU),吞吐量(或者缓解短缺)的提升情况。 正确性测试 在为某个并发类设计单元测试时...
Read More进程:每一个程序都在单独的进程中运行 线程:线程允许在同一个进程中同时存在多个控制流,会共享进程范围内的资源,是基本的调度单位 线程的优势? 发挥多处理器的强大能力 建模的简单性:执行同一种类型的任务,如Servlet 异步事件的简单化处理,如异步I/O 响应更灵敏的用户界面,如将长时间允许的任务放在一个单独的线程中运行,那么事件线程就能及时处理界面事件 线程带来的风险?</...
Read More委托是创建线程安全类的一个最有效的策略:只需让现有的线程安全类管理所有的状态即可。 同步容器类 实现线程安全的方式:将它们的状态封装起来,并对每个公有方法都进行同步,使得每次只有一个线程能访问容器的状态。 同步容器类的问题 在同步容器类中,这些复合操作(迭代,跳转,以及条件运算)在没有客户端加锁的情况下仍然是线程安全的,但其他线程并发地修改容器时,它们可能会表现出意外的行为。 //在客户端加锁的Vector上的复合操作 ...
Read More线程最主要的目的就是提高程序的运行性能。 对性能的思考 提升性能意味着用更少的资源做更多的事。当操作性能由于某种特定的资源而受到限制时,通常将该操作称为资源密集型的操作,如CPU密集型、数据库密集型。 造成性能开销的操作包括:线程之间的协调(如加锁,触发信号以及内存同步等),增加的上下文切换,线程的创建和销毁,以及线程的调度等。 要想通过并发来获得更好的性能,需要努力做好两件事情: 更有效地利用现有处理资源 在出现新的处理资源时使程序尽可能地利用这些资源。 <a href="#性能与可伸缩性" ...
Read More