Java高并发
来源:互联网 发布:淘宝扣12分以后怎么办 编辑:程序博客网 时间:2024/05/21 22:25
线程的基础知识
概念:线程是进程内的执行单元
Java中线程的基本操作
- 新建线程 :继承Thread类和实现Runnable接口
- 终止线程:Thread.stop()不推荐使用,因为会释放所有的monitor
- 中断线程:public void Thred.interrupt()public boolean Thread.isInterrupted()public stataic boolean Thread.interrupted()
- 挂起(suspend)和继续执行(resume)线程:suspend()不会释放锁,如果加锁发生在resume之前,则会发生死锁,不推荐使用
- 等待线程结束(join)和谦让(yeild)
- 守护线程:在后台默默完成一些系统性的服务,比如垃圾回收线程等;当一个Java应用内,只有守护线程时,Java虚拟机就会退出
- 线程优先级 Thread.setPriority()
- synchronized 加锁的三种方式:指定加锁对象、直接作用于实例方法、直接作用于静态方法
- Object.wait() 和Object.notify(): T1取得object监视器,wait释放object监视器;T2取得object监视器,object.notify()释放object监视器;T1等待object监视器,重获object监视器,继续执行 10.
为什么要并发?
业务模型的需要
- 业务上需要多个执行单元
- HTTP服务器,为每个Socket链接新建一个处理线程
- 让不同的线程处理不同的业务
- 简化任务调度
同步和异步
同步,就是在发出一个调用时,在没有得到结果之前,该 调用 就不返回。但是一旦调用返回,就得到返回值了
异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。也就是说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通知调用者,或通过回调函数处理这个调用。
并发和并行
并发的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。
并行性指两个或两个以上事件或活动在同一时刻发生。在多道程序环境下,并行性使多个程序同一时刻可在不同CPU上同时执行。
临界区
临界区是所有所有线程都能访问的公共资源(没一次只有一个线程使用,一旦临界区资源被占用,其他资源要使用必须等待)
阻塞和非阻塞
阻塞:若一个线程占用了临界区资源,则其他所有需要这个资源的线程就必须在这个临界区中进行等待,等待会导致线程挂起
非阻塞:允许多个线程同时进入临界区
死锁、活锁、饥饿
死锁:静态的,抢占资源不释放导致
活锁:线程申请资源失败时就会释放已经获得的资源,一直重复 尝试—失败—尝试—失败的过程
饥饿:线程一直获取不到资源,一直无法运行
并发级别
- 阻塞:当一个线程进入临界区,其他线程就必须等待
- 无障碍:
最弱的非阻塞调度
线程可以自由出去临界区
无竞争时,有限布内完成操作;
有竞争时,回滚数据 - 无锁:无障碍的,保证有一个线程胜出
- 无等待:无锁的,要求所有线程必须在有限步内完成;无饥饿的
无锁(Lock-Free)
原理:
CAS: 包含三个参数CAS(V,E,N) V:要更新的值;E:预期值;N:新值。当且仅当V和E相等时,才会将V值改为N,否则说明其他线程做了更新,当前线程什么也不做;CAS返回当前V的真实值。失败的线程不会被挂起,允许再次尝试(线程被挂起时大约需要8万个时钟周期,而一次重试只需要2-3个时钟周期)
无锁类
1.AtomicInteger
源码
private volatile int value;/** * Atomically sets to the given value and returns the old value. * * @param newValue the new value * @return the previous value */ public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); } /** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * * @param expect the expected value * @param update the new value * @return {@code true} if successful. False return indicates that * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
- AtomicInteger中真正存储数据的是value变量,而改变量是被volatile修饰的,保证了线程直接的可见性。
- getAndSet方法通过一个死循环不断尝试赋值操作。而真正的赋值操作交给了unsafe类来实现。
Unsafe
非安全的操作: - 根据偏移量设置值
- park()
- 底层的CAS操作
Unsafe类是CAS实现的核心
compareAndSwapInt
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
第一个参数是给定的对象,offset是对象内的偏移量(其实就是一个字段到对象头部的偏移量,通过这个偏移量可以快速定位字段),第三个参数是期望值,最后一个是要设置的值。
2.AtomicReference
对引用进行修改
例子
public static final AtomicReference<String> REFERENCE = new AtomicReference<String>("abc"); public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread() { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (REFERENCE.compareAndSet("abc", "cdf")) { System.out.println(Thread.currentThread().getName() + "修改成功"); } else { System.out.println(Thread.currentThread().getName() + "修改失败"); } }; }.start(); } }
是一个模板类,抽象化了数据类型
3.AtomicStampedInteger
为了解决ABA问题
例子
public class AtomicStampedReferenceDemo { static AtomicStampedReference<Integer> money = new AtomicStampedReference<Integer>(19, 0);// 余额 public static void main(String[] args) { // 模拟多个线程为用户充值 for (int i = 0; i < 3; i++) { final int timestamp = money.getStamp(); new Thread() { public void run() { while (true) { while (true) { Integer m = money.getReference(); if (m < 20) { if (money.compareAndSet(m, m + 20, timestamp, timestamp + 1)) { System.out.println("成功充值!" + "余额是:" + money.getReference()); break; } } else { // System.out.println("无需充值"); break; } } } }; }.start(); // 用户消费 new Thread() { public void run() { for (int i = 0; i < 4; i++) { while (true) { int timestamp = money.getStamp(); Integer m = money.getReference(); if (m > 10) { if (money.compareAndSet(m, m - 10, timestamp, timestamp + 1)) { System.out.println("成功消费10元!" + "余额是:" + money.getReference()); break; } } else { System.out.println("没有足够金额"); break; } } try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; }.start(); } }}
4.AtomicIntegerArray
支持无锁的数组
5.AtomicIntegerFieldUpdater
让普通变量也享受原子操作
:
1.Updater只能修改它可见范围内的变量。因为Updater使用反射得到这个变量,如果变量不可见,就会出错。比如private的变量,就不可行
2.为了确保变量被正确读取,必须是volatile
3.由于CAS操作会通过对象实例中的偏移量直接进行复制,因此不支持static字段,因为Unsafe.objectFieldOffset()不支持静态变量
例子
public class AtomicIntegerFieldUpdaterDemo { public static class Candidate { int id; volatile int score; } public final static AtomicIntegerFieldUpdater<Candidate> scoreUpdater = AtomicIntegerFieldUpdater .newUpdater(Candidate.class, "score"); // 检查Updater是否工作正确 public static AtomicInteger allScore = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { final Candidate stu = new Candidate(); Thread[] t = new Thread[10000]; for (int i = 0; i < 10000; i++) { t[i] = new Thread() { public void run() { if (Math.random() > 0.4) { scoreUpdater.incrementAndGet(stu); allScore.incrementAndGet(); } } }; t[i].start(); } for (int i = 0; i < 10000; i++) { t[i].join(); } System.out.println("score=" + stu.score); System.out.println("allScore=" + allScore); }}
- 并发 - java高并发解决方案
- java-并发-高并发概述
- java高并发、高性能
- java高并发解决方案
- java高并发解决方案
- java 高并发 基础知识
- java高并发解决方案
- java高并发解决方案
- java高并发解决方案
- java高并发解决方案
- java高并发解决方案
- java高并发处理
- java高并发解决方案
- java高并发解决方案
- java高并发解决方案
- java高并发编程
- java高并发解决方案
- java高并发解决方案
- 模型调用数据库数据,控制器输出模板
- Shell中 [ 和 [[ 的异同
- Nexus私服使Maven更加强大
- AVG PC Tuneup 2017(顶级系统优化大师)官方中文破解版64位V16.76.3.18604下载 | 内置avg pc tuneup 2017激活码
- git 码云上传本地项目代码
- Java高并发
- 结构型模式--桥接模式
- 稳压电源 连载10:提高稳定性的措施
- Android studio 导入githunb项目出现红圈解决方案
- sqlldr(导入)/sqluldr2(导出)工具的使用
- 函数的调用(栈帧的创建和销毁)
- MFC中运行出现问题“不支持尝试执行的操作”
- 运用ConvenientBanner实现Android界面图片轮播
- 深入分析JavaWeb技术内幕(修订版)》【PDF】下载