JUC
juc
java8一个工具类包
现程和进程
进程:一个程序,程序的集合,一个进程包含多个线程
线程:进行运算调度的最小单位
Tread ,Runnable,Callable
java不可以开启进程,是由本地方法调用开启线程的
并发和并行
并发:多线程操作同一个资源,交替执行
并行:同时执行不同的任务,同时执行
并发本质:充分利用CPU资源
线程有几个状态
6个状态
NEW:新生
RUNNABLE:运行
BLOCKED:阻塞
WAITING:等待
TIMED_WAITING:超时等待
TERMINATED:终止
wait和sleep区别
- 来着不同的类,wait:object类,sleep:Tread
- wait会释放锁,sleep不释放锁
- 使用范围不同,wait必须在同步代码中使用,sleep可以在任何地方使用
- 是否需要捕获异常,wait不需要捕获异常(待确认),sleep需要
Lock锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NvLILGCb-1617233445182)(C:\Users\zyq zt\AppData\Roaming\Typora\typora-user-images\image-20210330073420900.png)]
公平锁:十分公平,可以先来后到
非公平锁:可以插队
Synchronized如果用if 会使用虚假唤醒,要使用while
新版生产者消费者
JUC
多了指定唤醒的某个进程的功能 Condition
public class TestC {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.printC();
}
},"C").start();
}
}
class Data3{
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1;
public void printA(){
lock.lock();
try {
while (number!=1){
//等待
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"AAAA");
//唤醒指定的人
number = 2;
condition2.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (number!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"BBBB");
number = 3;
condition3.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (number!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"CCCC");
number = 1;
condition1.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
什么是锁
8锁问题
new this 具体的一个手机
class 锁的是模板
synchronized 锁的对象是方法的调用者!
- 普通同步方法的调用者是类的实例(实例化对象)
- 静态同步方法的调用者是类的对象(class对象)
ArrayList安全问题
不安全的,解决方法
public class ListTest {
public static void main(String[] args) {
// List<String> list =new ArrayList<>();
//方案一:
//效率低 使用sychronized
// List<String> list = new Vector<>();//解决方法1
//方案二:
// List<String> list = Collections.synchronizedList(new ArrayList<>());
//方案三:
//写入时复制 COW 计算机程序设计领域的一种优化策略
//多个线程调用的时候,list,读取的时候,固定的,写入覆盖
//在写入的时候避免覆盖,造成数据问题
//使用lock锁
List<String> list =new CopyOnWriteArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
Set同理
Set<String> set = Collections.synchronizedSet(new HashSet<>());
Set<String> set =new CopyOnWriteArraySet<>();
HashMap也是不安全
加载因子和初始化容量需要再了解一下!
public class MapTest {
public static void main(String[] args) {
// Map map = new HashMap<>();
//加载因子、初始化容量!!
Map map = new ConcurrentHashMap<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));
System.out.println(map);
},String.valueOf(i)).start();
}
}
}
Callable
public class CallableTest {
public static void main(String[] args) {
//注意这里调用方式
myThread thread = new myThread();
FutureTask futureTask = new FutureTask<>(thread);
new Thread(futureTask,"A").start();
}
}
//class myTread implements Runnable{ 不建议使用
//
// @Override
// public void run() {
//
// }
//}
class myThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("call()");
return 1024;
}
}
常用辅助类
CountDownLatch
减法计数器
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//总数是6,前面有必须执行的任务的时候使用
CountDownLatch countDownLatch = new CountDownLatch(6);
//-1
// countDownLatch.countDown();
for (int i = 0; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() +"go out");
countDownLatch.countDown();
},String.valueOf(i)).start();
}
countDownLatch.await();//等待计数器归零 再向下执行
System.out.println("close Door");
}
}
CyclicBarrier
加法计数器
public class CyclicBarrierDemo {
public static void main(String[] args) {
/**
*
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("成功");
});
for (int i = 0; i < 7; i++) {
final int temp = i;
new Thread(()->{
System.out.println(temp);
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
Semaphore
作用:多个共享资源互斥作用,并发限流,控制最大的线程数
public class SemaphoreDemo {
public static void main(String[] args) {
//线程数量 抢车位,限流的时候用得到
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
semaphore.acquire();//得到
System.out.println(Thread.currentThread().getName()+"抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
semaphore.release();//释放
}catch (InterruptedException e){
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
读写锁ReadWriteLock
独占锁(写锁):一次只能被一个线程占用
共享锁(读锁):多个线程可以同时占用
ReadWriteLock
读-读可以共存
读-写不能共存
写-写不能共存
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 1; i < 5; i++) {
final int temp = i;
new Thread(()->{
myCache.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
for (int i = 0; i < 5; i++) {
final int temp = i;
new Thread(()->{
myCache.get(temp+"");
},String.valueOf(i)).start();
}
}
}
/**
* 自定义缓存
*/
class MyCache {
private volatile Map<String,Object> map = new HashMap<>();
private ReentrantReadWriteLock lock =new ReentrantReadWriteLock();
//存,写
public void put(String key,Object value) {
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() +"写入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写入完毕");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.writeLock().unlock();
}
}
//读
public void get(String key) {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() +"读取"+key);
map.get(key);
System.out.println(Thread.currentThread().getName()+"读取完毕");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.readLock().unlock();
}
}
}
nlock();
}
}
//读
public void get(String key) {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() +"读取"+key);
map.get(key);
System.out.println(Thread.currentThread().getName()+"读取完毕");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.readLock().unlock();
}
}
}
### 阻塞队列