欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > java >内容正文

java

java并发编程实践 读书笔记_Java - 并发编程实践(读书笔记)

发布时间:2025/3/20 java 43 豆豆
生活随笔 收集整理的这篇文章主要介绍了 java并发编程实践 读书笔记_Java - 并发编程实践(读书笔记) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

[注] 同步机制保证:1)原子性 2)内存可见性;

Volatile变量只能保证:1)可见性; - 恰当的同步,同步的弱形式,确保对一个变量的更新以可预见的方式告知其他线程。

[注] 用锁来协调访问变量时,每次访问变量都需要用同一个锁。锁不仅仅是关于同步与互斥的,也是关于内存可见的。

为了保证所有线程都能够看到共享的、可变变量的最新值,读取和写入线程必须使用公共的锁进行同步。

[注] Java提供的内部锁是可重进入的,因为线程在试图获取它自己占有的锁时,请求会成功。重进入(Reenter)意味着锁的请求是基于"每线程",而不是基于"每调用";

[注] **本地(基于栈的)变量,不会被跨线程共享,因此不需要同步;

每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,栈内存可以理解为线程的私有内存;

[注] 线程中断是一个协作机制,每一个线程都有一个boolean类型的中断状态,在中断的时候,这个中断状态被设置为true。

阻塞库函数,比如:Thread.sleep()和Object.wait(),试图监测线程何时被中断,它们对中断的响应表现为:清除中断状态,抛出InterruptedException,这表示阻塞操作因为中断而提前结束。

[注] Volatile变量 vs 锁 :

Volatile变量与锁相比是更轻量的同步机制,它们不会引起上下文的切换和线程调度。然而,Volatile变量与锁相比有一些局限性:

尽管它们提供了相似的可见性保证,但是它们不能用于构建原子化的复合操作。这意味着当一个变量依赖其他变量时,或者当前变量的新值依赖于旧值时,是不能用Volatile变量的。

[注] 原子变量类 vs 锁 :

原子变量比锁更精巧,更轻量,因为它不会引起线程的挂起和重新调度;

CAS:compare and set; 非阻塞算法;

术语:检查并运行

[注] 条件队列:

Object中的wait、notify、notifyAll方法构成了内部条件队列的API;

一个对象的内部锁与它的内部条件队列是相关的,为了能够调用对象X的任一个条件队列方法,必须持有对象的锁;

条件谓语涉及状态变量,状态变量是由锁保护的,所以测试条件谓语之前,必须先持有锁;

* 锁、条件谓语和条件变量之间的三元关系,涉及条件谓词的变量必须由锁保护,检查条件谓词时以及调用wait和notify时,必须持有锁对象;

状态依赖方法的规范式:

void stateDependentMethod() throws InterruptedException{

//条件谓语必须被锁守护

synchronized(lock){

while(!conditionPredicate()){

lock.wait();

}

//现在,对象处于期望的状态中

}

}

Obejct.wait 内部流程:

1) 会自动释放锁,并请求OS挂起当前线程,让其他线程可以获得该锁进而修改对象的状态;

2) 线程被唤醒时,wait会重新请求与条件队列相关联的锁;

Object.notify:JVM从条件队列中等待的众多线程中挑选出一个并把它唤醒;

Object.notifyAll:JVM唤醒条件队列中等待的所有线程;(通常使用notifyAll)

[注] 一个公平的条件队列可以确保线程从等待集中释放的相对顺序,内部条件队列并不提供公平队列,显式的Condition可以提供公平/非公平队列的选择;

[注]Condition是显式的条件队列(await、signal、signalAll等方法),一个Condition与一个单独的Lock相关联,Lock.newCondition()可以创建一个Condition;

[注] Lock:显式锁,可中断的锁获取请求,中断将抛出InterruptedException;

public boolean sendOnShareLine(String message) throws InterruptedException{

lock.lockInterruptibly();

try{

return cancellableSendOnSharedLine(message);

}finally{

lock.unlock();

}

}

private boolean cancellableSendOnSharedLine(String message)

throws InterruptedException{ ... }

阻塞队列 BlockingQueue : LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue

1)阻塞方法:put()、take()

2)非阻塞方法:offer()、poll()

Executor框架 -任务执行框架:将任务的提交与任务的执行体进行解耦,可以简单的为给定的任务制定执行策略。

类库提供了一个灵活的线程池实现:ThreadPoolExecutor,以及一些有用的预设配置,可以通过 Executors中的静态工厂方法创建一个线程池:

newFixedThreadPool

newCachedThreadPool

newScheduledThreadPool

newSingleThreadExecutor

为了解决执行服务的生命周期问题,ExecutorService接口扩展了Executor,添加了一些用于生命周期管理的方法,同时还有一些用于任务提交的便利方法。

想要使用Executor,还必须能够将任务描述为Runnable。Executor框架使用Runnable作为其任务的基本表达形式。

- Runnable 只是相当有限的抽象,run方法不能返回值或者抛出受检查的异常;

- Callable 可携带结果的任务,可以把其他类型的任务封装成一个Callable;

一个Executor执行的任务的生命周期有4个阶段:创建、提交、开始和完成。

Future 用以描述"任务"的生命周期,提供方法来获得任务的结果、取消任务以及检查任务是否已经完成还是被取消。

有很多种方法可以创建一个描述任务的Future:

- 将一个Runnable或一个Callable提交给executor,然后得到一个描述任务执行的Future,如:ExecutorService.submit()方法;

- 显示为给定的Runnable或Callable实例化一个FutureTask;

public interface Callable{

V call() throws Exception;

}

public interface Future{

boolean cancel(boolean mayInterruptIfRunning);

boolean isCancelled();

boolean isDone();

V get() throws InterruptedException,ExecutionException,CancellationException;

V get(long timeout,TimeUnit unit)

throws InterruptedException,ExecutionException,CancellationException,TimeoutException;

}

可参考文章:

Java并发编程实战读后感 http://www.jianshu.com/p/c072cb0b4763

并发编程网-高质量并发译文 http://ifeve.com/doug-lea/

总结

以上是生活随笔为你收集整理的java并发编程实践 读书笔记_Java - 并发编程实践(读书笔记)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。