性能与可伸缩性
一、Amdahl定律
1.问题和资源的关系
在某些问题中,资源越多解决速度越快;而有些问题则相反:

注意:每个程序中必然有串行的部分,而合理的分析出串行和并行的部分对程序的影响极大;串行部分占比和多核执行效率之间是指数级别的关系
2.ConcurrentLinkedQueue
立即学习“Java免费学习笔记(深入)”;
在多核环境中,这个线程安全的队列比通过synchronizedList生成的队列速度要快很多
可以说:concurrent中提供的类,比通过方法生成的线程安全类速度要快
二、线程开销
由于多线程有开销:所以使用多线程必须保证性能的提升>并发的开销
上下文切换的开销
内存同步的开销
三、减少锁的竞争
1.减少锁持有时间:缩小锁的范围
private final Mapattributes = new HashMap ();//整个方法上锁public synchronized boolean userLocationMatches(String name, String regexp) { String key = "users." + name + ".location"; String location = attributes.get(key);if (location == null)return false;elsereturn Pattern.matches(regexp, location); }public boolean userLocationMatches(String name, String regexp) { String key = "users." + name + ".location"; String location;//只针对可变状态上锁synchronized (this) { location = attributes.get(key); }if (location == null)return false;elsereturn Pattern.matches(regexp, location); }
2.降低锁的请求频率:锁分解、锁分段...
锁分解:将一个锁分解为多个锁如:无需在一个原子操作中更新多个状态变量,每个状态变量却用的是同一个类锁,就没必要,每个不相干的状态变量的使用自己的锁就行
1、数据调用该功能使界面与程序分离实施变得更加容易,美工无需任何编程基础即可完成数据调用操作。2、交互设计该功能可以方便的为栏目提供个性化性息功能及交互功能,为产品栏目添加产品颜色尺寸等属性或简单的留言和订单功能无需另外开发模块。3、静态生成触发式静态生成。4、友好URL设置网页路径变得更加友好5、多语言设计1)UTF8国际编码; 2)理论上可以承担一个任意多语言的网站版本。6、缓存机制减轻服务器
public class ServerStatusBeforeSplit {public final Set users;public final Set queries;public ServerStatusBeforeSplit() {
users = new HashSet();
queries = new HashSet();
}//每个方法使用 当前class实例锁,类似于synchronized(this),不管是否是操作同一共享状态public synchronized void addUser(String u) {
users.add(u);
}public synchronized void addQuery(String q) {
queries.add(q);
}public synchronized void removeUser(String u) {
users.remove(u);
}public synchronized void removeQuery(String q) {
queries.remove(q);
}
}public class ServerStatusAfterSplit {public final Set users;public final Set queries;//操作同一 状态的方法 使用相同的锁public ServerStatusAfterSplit() {
users = new HashSet();
queries = new HashSet();
}public void addUser(String u) {synchronized (users) {
users.add(u);
}
}public void addQuery(String q) {synchronized (queries) {
queries.add(q);
}
}public void removeUser(String u) {synchronized (users) {
users.remove(u);
}
}public void removeQuery(String q) {synchronized (users) {
queries.remove(q);
}
}
}
锁分段:如将map桶分成不同的段,每个段都有一个锁,这样,在执行某些操作如get,就可以持有不同的锁从而提高并发效率,当然有些操作需要同时持有容器所有段的锁如clear等
//Map分段锁实现public class StripedMap {// Synchronization policy: buckets[n] guarded by locks[n%N_LOCKS]private static final int N_LOCKS = 16; //锁数量private final Node[] buckets; //容器桶private final Object[] locks; //同步监听器对象数组private static class Node {
Node next;
Object key;
Object value;
}public StripedMap(int numBuckets) {
buckets = new Node[numBuckets];
locks = new Object[N_LOCKS];for (int i = 0; i < N_LOCKS; i++)
locks[i] = new Object();
}private final int hash(Object key) {return Math.abs(key.hashCode() % buckets.length);
}public Object get(Object key) {int hash = hash(key);//获取当前 key对应的index区域的锁,只获取了一个锁synchronized (locks[hash % N_LOCKS]) {for (Node m = buckets[hash]; m != null; m = m.next)if (m.key.equals(key))return m.value;
}return null;
}public void clear() {for (int i = 0; i < buckets.length; i++) {//获取 每个i对应的锁,就是获取了整个容器所有的分段锁synchronized (locks[i % N_LOCKS]) {
buckets[i] = null;
}
}
}
}
3.避免热点域
热点资源的锁竞争激烈,导致的性能问题
4.替代独占锁
如:读-写锁:读读可并行,来防止独占;使用原子状态量;使用并发容器;使用不可变对象等
5.减少上下文切换
任务在阻塞于非阻塞的状态中切换,就类似于一次上下文切换
如:日志,日志的打印和IO操作会导致大量的阻塞和释放,导致性能问题









