Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int incrementAndGet() int get() int compareAndGet() Atomic类可以实现: 无锁(lock-free)实现的线程安全(thread-safe)访问 原理:CAS(Compare and Set)如果AtomicInteger实例的值是prev,就替换为next,返回…
Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等待状态,直到条件满足.线程唤醒以后,getTask()才会返回,而java.util.concurrent提供了线程安全的Blocking集合,如ArrayBlockingQueue. class TaskQueue{ final Queue<String> queue = new LinkedL…
线程同步: 是因为多线程读写竞争资源需要同步 Java语言提供了synchronized/wait/notify来实现同步 编写多线程同步很困难 所以Java提供了java.util.concurrent包: 更高级的同步功能 简化多线程程序的编写 JDK>= 1.5 java.util.locks.ReentrantLock用于替代synchronized加锁 synchronized是Java语言提供的,不需考虑异常 ReentrantLock是普通的Java类,要用try...finall…
Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配一个空闲线程执行 如果所有线程都处于忙碌状态,新任务放入队列等待 ExecutorService JDK提供了ExecutorService接口表示线程池: ExecutorService executor = Executors.newFixedThreadPool(4); //固定大小的线程池…
线程池可以高效执行大量小任务: Fork/Join线程池可以执行一种特殊的任务: 把一个大任务拆成多个小任务并行执行 Fork/Join是在JDK 1.7引入的 示例:计算一个大数组的和 Fork/Join就是把一个大人物不断的拆成小任务,执行并行计算的一种模式. class SumTask extends RecursiveTask<Long> { protected Long compute(){ //把一个大任务分拆成2个子任务 SumTask subtask1 = new Sumtas…
使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get(); 但是当我们使用get()获得异步执行结果的时候,这个方法可能会阻塞.我们通过while循环反复调用isDone()来判断异步结果是否已经完成. while(!future.isDone()){ Thread.sleep(1); } String result = future.get() 所以使用Futu…
JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务. ExecutorService executor = Executors.newFixedThreadPool(4); executor.submit(task); 但这里的task有个问题,因为继承制Runnable,如果希望返回一个结果,只能用Result来表示,这样主线程获取结果,就很不方便. class Task implements Runnable{ public String result…
Condition实现等待和唤醒线程 java.util.locks.ReentrantLock用于替代synchronized加锁 synchronized可以使用wait和notify实现在条件不满足时的等待,条件满足时的唤醒. class TaskQueue{ final Lock lock = new ReentrantLock() final Condition notEmpty = lock.newCondition(); } 使用Condition对象可以通过await和signa…
ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性.当有线程进入临界区段时,其他线程或是进程必须等待,有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用,例如:semaphore.只能被单一线程访问的设备,例如:打印机. public…
1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下代码 public void add(int m){ synchronized (lock){ this.value += m; another(m); } } public void addAnother(int m){ synchronized (lock){ this.another += m…