java并发编程实践读书笔记
线程的粗粒度将会给性能带来极大影响
可见性
- 在一个线程中也许无法确保能看到另一个线程写入的值,所以需要一定的同步机制
Volatile关键字
- Java语言提供了一种稍弱的同步机制,即是volatile变量,当声明为volatile时,编译和运行时将会注意到该变量是共享的,不会被缓存到寄存器或其他处理器不可见的地方,因此每一次将会返回最新写入的值,比sychronized关键字更轻量化
- volatile关键字只能确保其可见性
- 当满足一下条件,才能使用volatile
- 对变量的写入操作不依赖当前值,或者你能保证单个线程更新变量的值
- 该变量不会与其他条件纳入不变性条件中
- 在访问变量时不需要加锁
线程封闭
- 不共享数据,仅在单线程里面访问数据,这就是线程封闭
- Swing中大量使用了线程封闭,JDBC中通过connection的管理模式也实现了线程封闭
栈封闭
public int loadTheArk(Collection<Animal> candidates) {
SortedSet<Animal> animals;
int numPairs = 0;
Animal candidate = null;
animals = new TreeSet<Animal>(new SpeciesGenderComparator());
animals.addAll(candidates);
for (Animal a : animals) {
if (candidate == null || !candidate.isPotentialMate(a))
candidate = a;
else {
ark.load(new AnimalPair(candidate, a));
++numPairs;
candidate = null;
}
}
return numPairs;
}
ThreadLocal类
- 这是个由JDK提供的一个类,更规范,能将某个值和保存值的对象连接起来,提供了set和get的访问接口或方法
public class ConnectionDispenser {
static String DB_URL = "jdbc:mysql://localhost/mydatabase";
private ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
public Connection initialValue() {
try {
return DriverManager.getConnection(DB_URL);
} catch (SQLException e) {
throw new RuntimeException("Unable to acquire Connection, e");
}
};
};
public Connection getConnection() {
return connectionHolder.get();
}
}
同步容器类
- Vector和HashTable
- 迭代器与ConcurrentModificationException(并发修改错误)
class BadListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
public class HiddenIterator {
@GuardedBy("this") private final Set<Integer> set = new HashSet<Integer>();
public synchronized void add(Integer i) {
set.add(i);
}
public synchronized void remove(Integer i) {
set.remove(i);
}
public void addTenThings() {
Random r = new Random();
for (int i = 0; i < 10; i++)
add(r.nextInt());
System.out.println("DEBUG: added ten elements to " + set);
}
}
并发容器
Executor框架
- 基于Executor框架的web服务器
- 定长线程池,可以容纳100个线程
public class TaskExecutionWebServer {
private static final int NTHREADS = 100;
private static final Executor exec
= Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable task = new Runnable() {
public void run() {
handleRequest(connection);
}
};
exec.execute(task);
}
}
private static void handleRequest(Socket connection) {
}
}
- Executor的不同线程池
- newFixedThreadPool定长线程池
- newCachedThreadPool创建可缓存线程池,当线程词超过处理需求时,将回收空闲线程,而当需求增加时,则可以添加新的线程
- newSingleThreadExecutor是一个单线程的Executor
- newScheduledThreadPool,创建一个固定长度的线程池,而且以延时或者定时的方式来执行任务