读锁:共享锁
写锁:独占锁
都会发生死锁
读读不互斥,读写互斥,写写互斥
不带锁:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;class MyCache{//创建map集合private volatile Map map = new HashMap<>();//放数据public void put(String k,Object v) throws InterruptedException {System.out.println(Thread.currentThread( ).getName()+"正在放数据"+k);TimeUnit.MILLISECONDS.sleep(300);map.put(k,v);System.out.println(Thread.currentThread( ).getName()+"写完数据"+k);}//取数据public void get(String k) throws InterruptedException {Object res=null;System.out.println(Thread.currentThread( ).getName()+"正在取数据"+k);TimeUnit.MILLISECONDS.sleep(300);res=map.get(k);System.out.println(Thread.currentThread( ).getName()+"取完数据"+k);}
}
public class ReentrantReadWriteLockDemo {public static void main(String[] args) {MyCache myCache=new MyCache();for (int i = 1; i < 5; i++) {final int num=i;new Thread(()->{try {myCache.put(num+"",num);} catch (InterruptedException e) {e.printStackTrace();}},String.valueOf(i)).start();}for (int i = 1; i < 5; i++) {final int num=i;new Thread(()->{try {myCache.get(num+"");} catch (InterruptedException e) {e.printStackTrace();}},String.valueOf(i)).start();}}
}
会出现逻辑错误
加上读写锁
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;class MyCache{//创建map集合private volatile Map map = new HashMap<>();//创建读写锁对象private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();//放数据public void put(String k,Object v) {readWriteLock.writeLock().lock();try {System.out.println(Thread.currentThread( ).getName()+"正在放数据"+k);TimeUnit.MILLISECONDS.sleep(300);map.put(k,v);System.out.println(Thread.currentThread( ).getName()+"写完数据"+k);} catch (InterruptedException e) {e.printStackTrace();}finally {readWriteLock.writeLock().unlock();}}//取数据public void get(String k){readWriteLock.readLock().lock();try {Object res=null;System.out.println(Thread.currentThread( ).getName()+"正在取数据"+k);TimeUnit.MILLISECONDS.sleep(300);res=map.get(k);System.out.println(Thread.currentThread( ).getName()+"取完数据"+k);} catch (InterruptedException e) {e.printStackTrace();}finally {readWriteLock.readLock().unlock();}}
}
public class ReentrantReadWriteLockDemo {public static void main(String[] args) {MyCache myCache=new MyCache();for (int i = 1; i < 5; i++) {final int num=i;new Thread(()->{myCache.put(num+"",num);},String.valueOf(i)).start();}for (int i = 1; i < 5; i++) {final int num=i;new Thread(()->{myCache.get(num+"");},String.valueOf(i)).start();}}
}

读时候,不能写,只有读完成之后,才可以写,写操作的同时可以读。容易造成锁饥饿,一直读,没有写操作。
锁降级的步骤
获取写锁 -->>获取读锁 -->>释放写锁 -->>释放读锁
public static void main( String[] args) {//可重入读写锁对象ReentrantReadwriteLock rwLock = new ReentrantReadwriteLock();ReentrantReadwriteLock.ReadLock readLock = rwLock.readLock();//读锁ReentrantReadwriteLock.writeLock writeLock = rwLock.writeLock();//写锁//锁降级//1获取写锁writeLock.lock();system.out.println("123");//2获取读锁readLock.lock();system.out.println("456");//3释放写锁writeLock.unlock();//4释放读锁readLock.unlock();
}
阻塞队列,顾名思义,首先它是一个队列,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出;
好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你一手包办
基于数组的阻塞队列实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,这是一个常用的阻塞队列,除了一个定长数组外,ArrayBlockingQueue 内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。”
由数组结构组成的有界阻基队列。
ArrayBlockingQueue和LinkedBlockingQueue是两个最普通也是最常用的阻塞队列,一般情况下,在处理多线程间的生产者消费者问题,使用这两个类足以。·
一句话总结:由链表结构组成的有界(但大小默认值为integer.MAX_VALUE)阻塞队列
DelayQueue 中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue是一个没有大小限制的队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。
使用优先级队列实现的延迟无界阻塞队列
基于优先级的阻塞队列(优先级的判断通过构造函数传入的Compator对象来决定),但需要注意的是PriorityBlockingQueue并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。
支持优先级排序的无界阻塞队列
不存储元素的阻塞队列,也即单个元素的队列
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class BlockQueueDemo {public static void main(String[] args) throws InterruptedException {BlockingQueue blockQueue=new ArrayBlockingQueue<>(3);blockQueue.put("a");blockQueue.put("b");blockQueue.put("c");//blockQueue.put("d");会阻塞System.out.println(blockQueue.take());System.out.println(blockQueue.take());System.out.println(blockQueue.take());//System.out.println(blockQueue.take());会阻塞}
}
线程池的优势: 线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。
它的主要特点为:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo1 {public static void main(String[] args) {//一池5线程ExecutorService executorService = Executors.newFixedThreadPool(5);//10个任务try {for (int i = 1; i <=10 ; i++) {//执行executorService.execute(()->{System.out.println(Thread.currentThread() .getName()+"处理任务ing...");});}}catch (Exception e){e.printStackTrace();}finally {//关闭线程池executorService.shutdown();}}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo2 {public static void main(String[] args) {//一池1线程ExecutorService executorService = Executors.newSingleThreadExecutor();//10个任务try {for (int i = 1; i <=10 ; i++) {//执行executorService.execute(()->{System.out.println(Thread.currentThread() .getName()+"处理任务ing...");});}}catch (Exception e){e.printStackTrace();}finally {//关闭线程池executorService.shutdown();}}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo3 {public static void main(String[] args) {//根据需求创建线程,可扩容ExecutorService executorService = Executors.newCachedThreadPool();//10个任务try {for (int i = 1; i <=100 ; i++) {//执行executorService.execute(()->{System.out.println(Thread.currentThread() .getName()+"处理任务ing...");});}}catch (Exception e){e.printStackTrace();}finally {//关闭线程池executorService.shutdown();}}
}
newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool底层都是new了ThreadPoolExecutor
ThreadPoolExecutor有七个参数
| 参数 | 意义 |
|---|---|
| int corePoolsize | 核心线程数量 |
| int maximumPoolsize, | 最大线程数量 |
| long keepAliveTime | 线程存活时间的值 |
| TimeUnit unit | 线程存活时间的单位 |
| BlockingQueue workQueue | 阻塞队列 |
| ThreadFactory threadFactory | 线程工厂 用于创建线程 |
| RejectedExecutionHandler handler | 拒绝策略 |

拒绝策略:

import java.util.concurrent.*;public class ThreadPoolDemo4 {public static void main(String[] args) {ExecutorService executorService = new ThreadPoolExecutor(2, 5, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());//10个任务try {for (int i = 1; i <=10 ; i++) {//执行executorService.execute(()->{System.out.println(Thread.currentThread() .getName()+"处理任务ing...");});}}catch (Exception e){e.printStackTrace();}finally {//关闭线程池executorService.shutdown();}}
}
Fork:把一个复杂任务进行分拆
Join:把分拆任务的结果进行合并
计算1+2+…100 其中查分值不能超过10(二分法)
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;class MyThread extends RecursiveTask {private static final Integer VALUE = 10;//拆分差值private int begin;private int end;private int result;public MyThread(int begin,int end) {this.begin=begin;this.end=end;}@Overrideprotected Integer compute() {//判断相加两个数值是否大于10if((end-begin)<=VALUE) {//相加操作for (int i = begin; i <=end; i++) {result = result+i;}} else {//进一步拆分//获取中间值int middle =(end + begin)/2;//拆分MyThread thread01 = new MyThread(begin,middle);MyThread thread02 = new MyThread(middle+1,end);thread01.fork();thread02.fork();result=thread01.join()+thread02.join();}return result;}
}
public class demo01 {public static void main(String[] args) throws ExecutionException, InterruptedException {MyThread thread = new MyThread(1,100);//创建分支合并池对象ForkJoinPool forkJoinPool = new ForkJoinPool();//加入任务ForkJoinTask submit = forkJoinPool.submit(thread);//获取结果Integer result = submit.get();System.out.println(result);forkJoinPool.shutdown();}
}
package com.ynx.exarejuc;import org.apache.coyote.http11.filters.VoidInputFilter;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class Completable {public static void main(String[] args) throws ExecutionException, InterruptedException {//异步调用没有返回值CompletableFuture completableFuture1=CompletableFuture.runAsync(()->{System.out.println(Thread.currentThread().getName()+"completableFuture1");});completableFuture1.get();//异步调用有返回值CompletableFuture completableFuture2=CompletableFuture.supplyAsync(()->{System.out.println(Thread.currentThread().getName()+"completableFuture2");//int a=1/0;return 1024;});completableFuture2.whenComplete((t,u)->{System.out.println("t:::"+t);//返回值System.out.println("u:::"+u);//异常的信息}).get();}
}
上一篇:页面转变为灰色,如此简单
下一篇:四、值类型 和 引用类型