(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程(一)⭐学妹已收藏

news/2024/2/28 2:17:36

🔥(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程(一)⭐学妹已收藏

❤️‍ 大家好,我是java厂长,今天带你们体验一把多线程高并发的面试高频!❤️‍

关于作者

  • 作者介绍

🍓 博客主页:作者主页

🍓 简介:JAVA领域优质创作者🥇、一名在校大三学生🎓、在校期间参加各种省赛、国赛,斩获一系列荣誉🏆。

🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨‍💻。

JUC学习

文章目录

  • 🔥(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程(一)⭐学妹已收藏
    • 关于作者
    • JUC学习
      • 1、什么是JUC
      • 2、线程和进程
        • 面试题:谈一谈wait和sleep区别?
      • 3、Lock锁(重点)
      • 4、生产者消费者问题
      • 5、8锁现象
      • 6、集合不安全
      • 7、Callable
      • 8、常用的辅助类
        • 1) CountDownLatch—减法计数器
        • 2) CyclicBarrier—加法计数器
        • 3) Semaphore
      • 9、读写锁ReadwriteLock
      • 10、堵塞队列
        • 1) 四组API
        • 2) SynchronizedQueue 同步队列
      • 11、线程池
        • 1) 线程池的好处:
        • 2) 线程池: 三大方法
        • 3) 七大参数
        • 4) 拒绝策略
      • 12、四大函数式接口
        • 1) Function函数型接口
        • 2) Predicate 断定型接口
        • 3) Suppier 供给型接口
        • 4) Consummer 消费型接口
      • 13、Stream 流式计算
      • 14、ForkJoin—多线并发处理框架
        • 1)ForkJoin 特点: 工作窃取!
      • 2)如果使用ForkJoin
      • ❤️‍❤️‍❤️‍最后(学妹照片)

1、什么是JUC

image-20211009154114352
源码+官方文档

JUC是 java util concurrent

面试高频问JUC~!

image-20210905132518254

java.util 是Java的一个工具包

业务:普通的线程代码 Thread

Runnable: 没有返回值、效率相比于Callable 相对较低!

image-20210905132651962

2、线程和进程

进程:一个程序,允许一个java程序会进程里面会出现一个java.exe;数据+代码+pcb

一个进程可以包含多个线程,至少包含一个线程!

Java默认有几个线程?2个线程! main线程、GC线程

线程:开了一个进程qq,聊天打字,消息提示(线程负责的)

对于Java而言:Thread、Runable、Callable进行开启线程的。

JAVA真的可以开启线程吗? 开不了的!
原因Java没有权限去开启线程、操作硬件的,这是一个native的一个本地方法,它调用的底层的C++代码。

并发、并行

并发: 多线程操作同一个资源。

  • CPU 只有一核,模拟出来多条线程,那么我们就可以使用CPU快速交替,来模拟多线程。

并行: 多个人并排行走。

  • CPU多核,多个线程可以同时执行。
public class Test {public static void main(String[] args) {//获取cpu的核数System.out.println(Runtime.getRuntime().availableProcessors());}
}

并发编程的本质:充分利用CPU的资源!

线程的6个状态

public enum State {//创建NEW,//运行RUNNABLE,//阻塞BLOCKED,//等待WAITING,//超时等待TIMED_WAITING,//终止TERMINATED;}

面试题:谈一谈wait和sleep区别?

区别waitsleep
操作的类ObjectThread
锁的释放会释放锁抱着锁睡觉
范围同步代码块中任何地方
异常捕获不需要捕获异常需要捕获异常

3、Lock锁(重点)

synchronized锁问题

package com.zmz.day01;
/*** @ProjectName: Juc* @Package: com.zmz.day01* @ClassName: TicketTest* @Author: 张晟睿* @Date: 2021/9/5 14:01* @Version: 1.0*/
//资源类 属性 + 方法 oop
class Ticket{private int num = 50;//卖票方式  synchronized 本质:队列 锁public synchronized void sale(){if(num > 0){System.out.println(Thread.currentThread().getName()+ " 卖出了第"+ num +" 张票,剩余:"+ --num +" 张票");}}
}public class TicketTest {public static void main(String[] args) {//多线陈操作//并发:多个线程操作同一个资源ticketTicket ticket = new Ticket();//@FunctionalInterface 函数式接口 jdk1.8之后 lambda表达式new Thread(()->{for (int i = 0; i < 60; i++) {ticket.sale();}},"A").start();new Thread(()->{for (int i = 0; i < 60; i++) {ticket.sale();}},"B").start();new Thread(()->{for (int i = 0; i < 60; i++) {ticket.sale();}},"C").start();}
}

Lock接口

image-20210905160728862

image-20210905161116623

image-20210905161329587

公平锁: 公平,必须先来后到~;

非公平锁: 不公平,可以插队;(默认为非公平锁)

使用Lock进行操作

package com.zmz.day01;/*** @ProjectName: Juc* @Package: com.zmz.day01* @ClassName: TicketTest2* @Author: 张晟睿* @Date: 2021/9/5 16:15* @Version: 1.0*/import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/***@ClassName TicketTest2*@Description*@Author 张晟睿*@Date 2021/9/5**/class Ticket2{/** 加锁三步* 1.实例化lock对象* 2.lock加锁* 3.unlock解锁* */Lock l = new ReentrantLock();private int num = 50;//卖票方式  synchronized 本质:队列 锁public  void sale(){//加锁l.lock();try {//业务代码if(num > 0){System.out.println(Thread.currentThread().getName()+ " 卖出了第"+ num +" 张票,剩余:"+ --num +" 张票");}} catch (Exception e) {e.printStackTrace();} finally {//解锁l.unlock();}}
}public class TicketTest2 {public static void main(String[] args) {//多线陈操作//并发:多个线程操作同一个资源ticketTicket ticket = new Ticket();//@FunctionalInterface 函数式接口 jdk1.8之后 lambda表达式new Thread(()->{for (int i = 0; i < 60; i++) {ticket.sale();}},"A").start();new Thread(()->{for (int i = 0; i < 60; i++) {ticket.sale();}},"B").start();new Thread(()->{for (int i = 0; i < 60; i++) {ticket.sale();}},"C").start();}
}
区别synchronizedlock
名称属于关键字属于对象
状态不可以获取锁的状态可以获取锁的状态
锁的管理自动释放锁需要手动加锁以及释放锁
线程自己抱着锁等待
可重入锁,不可以中断的,非公平的可重入的,可以判断锁,可以自己设置公平锁和非公平锁
代码同步适合少量的代码同步适合大量的代码同步

4、生产者消费者问题

synchronized版

package com.zmz.day01;
/*** @ProjectName: Juc* @Package: com.zmz.day01* @ClassName: TicketTest3* @Author: 张晟睿* @Date: 2021/9/5 16:35* @Version: 1.0*//***@ClassName TicketTest3*@Description*@Author 张晟睿*@Date 2021/9/5**/
public class TicketTest3 {public static void main(String[] args) {Data data = new Data();new Thread(()->{for (int i = 0; i < 10; i++) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"B").start();}
}//判断等待  业务  唤醒
class Data{private int number = 0;//      +1操作public synchronized void increment() throws InterruptedException {if(number != 0 ){this.wait();}number++;System.out.println(Thread.currentThread().getName()+"=>"+number);this.notifyAll();}//      -1操作public synchronized void decrement() throws InterruptedException{if (number == 0){this.wait();}number--;System.out.println(Thread.currentThread().getName()+"=>"+number);this.notifyAll();}
}

问题存在,A线程B线程,现在如果我有四个线程A B C D!该怎么去解决问题

image-20210905165744242

if判断改为While判断就可以解决虚假唤醒的问题。

package com.zmz.day01;
/*** @ProjectName: Juc* @Package: com.zmz.day01* @ClassName: TicketTest3* @Author: 张晟睿* @Date: 2021/9/5 16:35* @Version: 1.0*//***@ClassName TicketTest3*@Description*@Author 张晟睿*@Date 2021/9/5**/
//线程之间的通讯问题:生产者和消费者的问题!  等待唤醒,通知唤醒
//线程交替执行 A   B操作同一个资源
public class TicketTest3 {public static void main(String[] args) {Data data = new Data();new Thread(()->{for (int i = 0; i < 10; i++) {try {data.increment();} catch (InterruptedException e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"B").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"C").start();new Thread(()->{for (int i = 0; i < 10; i++) {try {data.decrement();} catch (InterruptedException e) {e.printStackTrace();}}},"D").start();}
}//判断等待  业务  唤醒
class Data{private int number = 0;//      +1操作public synchronized void increment() throws InterruptedException {while(number != 0 ){this.wait();}number++;System.out.println(Thread.currentThread().getName()+"=>"+number);this.notifyAll();}//      -1操作public synchronized void decrement() throws InterruptedException{while (number == 0){this.wait();}number--;System.out.println(Thread.currentThread().getName()+"=>"+number);this.notifyAll();}
}

JUC版本的解决A B C D多线程的问题

image-20210905193408839

package com.zmz.day01;
/*** @ProjectName: Juc* @Package: com.zmz.day01* @ClassName: JucTest1* @Author: 张晟睿* @Date: 2021/9/5 19:34* @Version: 1.0*/import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/***@ClassName JucTest1*@Description*@Author 张晟睿*@Date 2021/9/5**/
public class JucTest1 {public static void main(String[] args) {Data2 data = new Data2();new Thread(()->{for(int i=0;i<10;i++) {data.increment();}},"A").start();new Thread(()->{for(int i=0;i<10;i++) {data.decrement();}},"B").start();new Thread(()->{for(int i=0;i<10;i++) {data.increment();}},"C").start();new Thread(()->{for(int i=0;i<10;i++) {data.decrement();}},"D").start();}
}class Data2{private int number = 0;//lock锁Lock l = new ReentrantLock();Condition condition = l.newCondition();public void increment() {l.lock();try {//业务while (number!=0){//等待操作condition.await();}number++;System.out.println(Thread.currentThread().getName()+"=>"+number);//通知其他线程 我+1完毕了condition.signalAll();} catch (InterruptedException e) {e.printStackTrace();} finally {l.unlock();}}public void decrement()  {l.lock();try {//业务while (number==0){//等待操作condition.await();}number--;System.out.println(Thread.currentThread().getName()+"=>"+number);//通知其他线程 我-1完毕了condition.signalAll();} catch (InterruptedException e) {e.printStackTrace();} finally {l.unlock();}}
}

Condition的优势:精准通知、唤醒的线程

package com.zmz.day01;
/*** @ProjectName: Juc* @Package: com.zmz.day01* @ClassName: JucTest2* @Author: 张晟睿* @Date: 2021/9/5 19:52* @Version: 1.0*/import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/***@ClassName JucTest2*@Description*@Author 张晟睿*@Date 2021/9/5**/
public class JucTest2 {public static void main(String[] args) {Data3 data3 = new Data3();new Thread(()->{for(int i=0;i<10;i++){data3.printA();}},"A").start();new Thread(()->{for(int i=0;i<10;i++){data3.printB();}},"B").start();new Thread(()->{for(int i=0;i<10;i++){data3.printC();}},"C").start();}
}class Data3{private Lock l = new ReentrantLock();Condition condition1 = l.newCondition();Condition condition2 = l.newCondition();Condition condition3 = l.newCondition();private int flag = 1;public void printA(){l.lock();//判断 -> 执行 -> 通知try {while(flag != 1){//等待condition1.await();}System.out.println(Thread.currentThread().getName() + "->A" );flag = 2;//唤醒指定线程condition2.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {l.unlock();}}public void printB(){l.lock();//判断 -> 执行 -> 通知try {while(flag != 2){//等待condition2.await();}System.out.println(Thread.currentThread().getName() + "->BB" );flag = 3;//唤醒指定线程condition3.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {l.unlock();}}public void printC(){l.lock();//判断 -> 执行 -> 通知try {while(flag != 3){//等待condition3.await();}System.out.println(Thread.currentThread().getName() + "->CCC" );flag = 1;//唤醒指定线程condition1.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {l.unlock();}}
}

5、8锁现象

1-2锁

package com.zmz.lock8;/*** @ProjectName: Juc* @Package: com.zmz.lock8* @ClassName: Test1* @Author: 张晟睿* @Date: 2021/9/5 21:18* @Version: 1.0*/import java.util.concurrent.TimeUnit;/***@ClassName Test1*@Description*@Author 张晟睿*@Date 2021/9/5**/
/*
* 8锁,就是关于锁的8个问题
* 1、标准情况下,两个线程先打印 发短信还是打电话?  发短信
* 2、sendSms方法延迟4s,两个线程先打印 发短信还是打电话?  发短信
* */
public class Test1 {public static void main(String[] args) {Phone phone = new Phone();//锁存在new Thread(()->{phone.sendSms();},"A").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{phone.call();},"B").start();}
}class Phone{//synchronized锁的对象是方法的调用者!//两个方法用的都是phone对象的锁!//谁先拿到谁执行!public synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信");}public synchronized void call(){System.out.println("打电话");}
}

image-20210906195336972

3-4锁

package com.zmz.lock8;/*** @ProjectName: Juc* @Package: com.zmz.lock8* @ClassName: Test2* @Author: 张晟睿* @Date: 2021/9/5 21:26* @Version: 1.0*/import java.util.concurrent.TimeUnit;/***@ClassName Test2*@Description*@Author 张晟睿*@Date 2021/9/5**/
//3、增加一个普通方法后! 发短信还是Hello,发短信       hello
//4、两个对象,两个同步方法,发短信还是打电话      打电话
public class Test2 {public static void main(String[] args) {//两个对象,两把锁Phone2 phone = new Phone2();Phone2 phone2 = new Phone2();//锁存在new Thread(()->{phone.sendSms();},"A").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{phone2.call();},"B").start();}
}
class Phone2{//synchronized锁的对象是方法的调用者!public synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信");}public synchronized void call(){System.out.println("打电话");}//这里没有锁!bubu不是同步方法,不受锁的影响public void hello(){System.out.println("hello");}
}

image-20210906195522569

image-20210906195548823

5-6锁

package com.zmz.lock8;/*** @ProjectName: Juc* @Package: com.zmz.lock8* @ClassName: Test3* @Author: 张晟睿* @Date: 2021/9/6 12:35* @Version: 1.0*/import java.util.concurrent.TimeUnit;/***@ClassName Test3*@Description*@Author 张晟睿*@Date 2021/9/6**/
/*
* 5、增加两个静态同步方法,只有一个对象,先打印发短信还是打电话?  发短信
* 6、两个对象!增加两个静态同步方法,只有一个对象,先打印发短信还是打电话  发短信
* */
public class Test3 {public static void main(String[] args) {//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone3 phone = new Phone3();Phone3 phone2 = new Phone3();//锁存在new Thread(()->{phone.sendSms();},"A").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{phone2.call();},"B").start();}
}
//Phone3唯一的一个Class对象
class Phone3{//synchronized锁的对象是方法的调用者!//static 静态方法//类一加载就有了!Class 模板 锁的是Classpublic static synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信");}public static synchronized void call(){System.out.println("打电话");}
}

image-20210906195751643

7-8锁

package com.zmz.lock8;/*** @ProjectName: Juc* @Package: com.zmz.lock8* @ClassName: Test4* @Author: 张晟睿* @Date: 2021/9/6 13:07* @Version: 1.0*/import java.util.concurrent.TimeUnit;/***@ClassName Test4*@Description*@Author 张晟睿*@Date 2021/9/6**/
/*
* 1个静态同步方法,1个同步方法,1个对象 先打印发短信还是打电话?   打电话
* 1个静态同步方法,1个同步方法,2个对象 先打印发短信还是打电话?   发短信
* */
public class Test4 {public static void main(String[] args) {//两个对象,两个调用者,两把锁!//两个对象的class类模板只有一个,static,锁的是ClassPhone4 phone = new Phone4();//锁存在new Thread(()->{phone.sendSms();},"A").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{phone.call();},"B").start();}
}
//Phone4唯一的一个Class对象
class Phone4{//synchronized锁的对象是方法的调用者!//锁的是Class类模板public static synchronized void sendSms(){try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("发短信");}//锁的是调用者public synchronized void call(){System.out.println("打电话");}}

image-20210906200040197

6、集合不安全

1、ArrayList集合不安全

package com;/*** @ProjectName: Juc* @Package: com* @ClassName: unsafe* @Author: 张晟睿* @Date: 2021/9/6 19:37* @Version: 1.0*/import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;/***@ClassName unsafe*@Description*@Author 张晟睿*@Date 2021/9/6**/
public class unsafe {public static void main(String[] args) {//高并发下的ArrayList真的安全么?/*** 解决方法* 1、List<String> list = new Vector<String>();* 2、List<String> list = Collections.synchronizedList(new ArrayList<>());* 3、List<String> list = new CopyOnWriteArrayList<>();* */List<String> list = new CopyOnWriteArrayList<>();//启动10个多线程for (int i = 1; i < 10; i++) {new Thread(() -> {list.add(UUID.randomUUID().toString().substring(0, 5));System.out.println(list);}, String.valueOf(i)).start();}}
}

CopyOnWriteArrayList源码分析

image-20210906201711960

2、Set不安全

package com.zmz.unsafe;/*** @ProjectName: Juc* @Package: com.zmz.unsafe* @ClassName: SetSafe* @Author: 张晟睿* @Date: 2021/9/6 21:20* @Version: 1.0*/import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;/***@ClassName SetSafe*@Description*@Author 张晟睿*@Date 2021/9/6**/
public class SetSafe {public static void main(String[] args) {//Set<String> set = new HashSet<>();//Set<String> set = Collections.synchronizedSet(new HashSet<>());Set<String> set = new CopyOnWriteArraySet<>();for (int i = 1; i < 60; i++) {new Thread(() -> {set.add(UUID.randomUUID().toString().substring(0, 5));System.out.println(set);}, String.valueOf(i)).start();}}
}

HashSet源码

    public HashSet() {map = new HashMap<>();}//HashSet本质就是Map集合public boolean add(E e) {return map.put(e, PRESENT)==null;}private static final Object PRESENT = new Object();//不变的值

3、HashMap不安全

package com.zmz.unsafe;/*** @ProjectName: Juc* @Package: com.zmz.unsafe* @ClassName: MapSafe* @Author: 张晟睿* @Date: 2021/9/6 21:27* @Version: 1.0*/import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;/***@ClassName MapSafe*@Description*@Author 张晟睿*@Date 2021/9/6**/
public class MapSafe {public static void main(String[] args) {//Map<String,String> map = new HashMap<>();//Map<String, Object> map = Collections.synchronizedMap(new HashMap<>());Map<String, Object> map = new ConcurrentHashMap<>();for (int i = 1; i <= 30; i++) {new Thread(()->{map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5));System.out.println(map);},String.valueOf(i)).start();}}
}

7、Callable

image-20211003164617870

  1. 可以有返回值
  2. 可以抛出异常
  3. 方法不同,run()/call()

callable源码

image-20211003171412542

image-20211003172936108

image-20211003173013110

image-20211004170058503

代码测试

package com.zmz.callable;/*** @ProjectName: Juc* @Package: com.zmz.callable* @ClassName: CallableTest* @Author: 张晟睿* @Date: 2021/10/3 16:52* @Version: 1.0*/import com.sun.org.apache.bcel.internal.generic.NEW;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/***@ClassName CallableTest*@Description*@Author 张晟睿*@Date 2021/10/3**/
public class CallableTest {public static void main(String[] args) throws ExecutionException, InterruptedException {// new Thread(new Runnable()).start();// new Thread(new FutureTask<V>()).start();// new Thread(new FutureTask<V>( Callable )).start();new Thread().start();MyThread myThread = new MyThread();FutureTask futureTask = new FutureTask(myThread);//适配类new Thread(futureTask,"A").start();new Thread(futureTask,"B").start(); //结果存在缓存提交效率Integer o = (Integer) futureTask.get();//获取返回的结果//这个get方法可以会产生阻塞! 解决办法 放到最后一行或者异步通信System.out.println(o);}
}
class MyThread implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println("call()方法");//耗时操作return 1024;}
}
/*
1、有缓存
2、结果可能会等待,阻塞
*/

8、常用的辅助类

1) CountDownLatch—减法计数器

package com.zmz.assist;/*** @ProjectName: Juc* @Package: com.zmz.assist* @ClassName: CountDownLatchDemo* @Author: 张晟睿* @Date: 2021/10/3 18:00* @Version: 1.0*/import java.util.concurrent.CountDownLatch;/***@ClassName CountDownLatchDemo*@Description*@Author 张晟睿*@Date 2021/10/3**/
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {CountDownLatch count = new CountDownLatch(10);for (int i = 1; i <= 10; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName() + "Go out");count.countDown();//数量-1},String.valueOf(i)).start();}count.await();//等计数器归零,然后再往下执行System.out.println("Close Door");}
}

原理:

  • count.countDown();//数量-1
  • count.await();//等待计数器归零。然后再向下执行

每次有线程用countDown()数量-1,如果计算器变为0了,然后count.await()就被唤醒,继续下面的执行!

2) CyclicBarrier—加法计数器

package com.zmz.assist;/*** @ProjectName: Juc* @Package: com.zmz.assist* @ClassName: CycilcBarrierDemo* @Author: 张晟睿* @Date: 2021/10/3 18:23* @Version: 1.0*/import com.sun.org.apache.bcel.internal.generic.NEW;import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;/***@ClassName CycilcBarrierDemo*@Description*@Author 张晟睿*@Date 2021/10/3**/
public class CycilcBarrierDemo {public static void main(String[] args) throws BrokenBarrierException, InterruptedException {CyclicBarrier barrier = new CyclicBarrier(7,()->{System.out.println("你已经凑齐了七颗龙珠!可以变身了");});for (int i = 1; i <= 7; i++) {final int temp = i;new Thread(()->{System.out.println(Thread.currentThread().getName()+ "收集" +(temp) +"颗龙珠");try {barrier.await();//等待} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}).start();}}
}

3) Semaphore

Semaphore:信号量,很多时候用来处理高并发。

image-20211003192250711

package com.zmz.assist;/*** @ProjectName: Juc* @Package: com.zmz.assist* @ClassName: SemaphoreDemo* @Author: 张晟睿* @Date: 2021/10/3 19:32* @Version: 1.0*/import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;/***@ClassName SemaphoreDemo*@Description*@Author 张晟睿*@Date 2021/10/3**/
public class SemaphoreDemo {public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);for (int i = 1; i <= 6; i++) {new Thread(()->{try {semaphore.acquire();//获得System.out.println(Thread.currentThread().getName()+"得到车位");TimeUnit.SECONDS.sleep(2);System.out.println(Thread.currentThread().getName()+"离开车位");} catch (InterruptedException e) {e.printStackTrace();}   finally {semaphore.release();//释放}},String.valueOf(i)).start();}}
}

原理:

  • acquire():获得,假设已经满了组需要等待,直到被释放为止

  • release():释放,会将当前的信号量释放+1,然后唤醒等待的线程!

    作用:多个共享的资源互斥使用!并发限流控制最大的线程数量!

9、读写锁ReadwriteLock

image-20211003195425532

package com.zmz.lock;/*** @ProjectName: Juc* @Package: com.zmz.lock* @ClassName: ReadwritelockDemo* @Author: 张晟睿* @Date: 2021/10/3 20:48* @Version: 1.0*/import java.util.HashMap;
import java.util.Map;/***@ClassName ReadwritelockDemo*@Description*@Author 张晟睿*@Date 2021/10/3**/
public class ReadwritelockDemo {public static void main(String[] args) {Mycache mycache = new Mycache();//写入for (int i = 1; i < 6; i++) {final int temp = i;new Thread(()->{mycache.put(temp+"",temp+"");},String.valueOf(i)).start();}//读取for (int i = 1; i < 6; i++) {final int temp = i;new Thread(()->{mycache.get(temp+"");},String.valueOf(i)).start();}}
}class Mycache{private volatile Map<String , Object> map = new HashMap<>();public void put(String key, Object value){System.out.println(Thread.currentThread().getName() + "写入" + key);map.put(key,value);System.out.println(Thread.currentThread().getName() + "写入完成");}public void get(String key){System.out.println(Thread.currentThread().getName() + "读取" + key);Object o = map.get(key);System.out.println(Thread.currentThread().getName() + "读取完成");}
}/*
1写入1
5写入5
5写入完成
4写入4
4写入完成
3写入3
2写入2
1读取1
3写入完成
1写入完成
2读取2
2读取完成
3读取3
3读取完成
1读取完成
2写入完成
5读取5
5读取完成
4读取4
4读取完成
*/

我们可以看到出现了严重的插队问题!该如何去解决囊?我们使用读写锁来解决插队的问题。

修改后的操作

package com.zmz.lock;/*** @ProjectName: Juc* @Package: com.zmz.lock* @ClassName: ReadwritelockDemo* @Author: 张晟睿* @Date: 2021/10/3 20:48* @Version: 1.0*/import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @ClassName ReadwritelockDemo* @Description* @Author 张晟睿* @Date 2021/10/3**//*
*独占锁 (写锁)一次只能被一个线程占有
*共享锁 (读锁)多个线程可以同时占有
* ReadWriteLock
* 读-读   可以共存
* 读-写   不可以共存
* 写-写   不可以共存
* */
public class ReadwritelockDemo {public static void main(String[] args) {MycacheLock mycache = new MycacheLock();//写入for (int i = 1; i < 6; i++) {final int temp = i;new Thread(() -> {mycache.put(temp + "", temp + "");}, String.valueOf(i)).start();}//读取for (int i = 1; i < 6; i++) {final int temp = i;new Thread(() -> {mycache.get(temp + "");}, String.valueOf(i)).start();}}
}
//加锁
class MycacheLock {private volatile Map<String, Object> map = new HashMap<>();//读写锁:更加细粒度的控制ReadWriteLock readWriteLock = new ReentrantReadWriteLock();//存、写的时候,只希望同时只有一个线程写public void put(String key, Object value) {readWriteLock.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 {readWriteLock.writeLock().unlock();}}//取、读所有人都可以进行操作public void get(String key) {readWriteLock.readLock().lock();try {System.out.println(Thread.currentThread().getName() + "读取" + key);Object o = map.get(key);System.out.println(Thread.currentThread().getName() + "读取完成");} catch (Exception e) {e.printStackTrace();} finally {readWriteLock.readLock().unlock();}}
}class Mycache {private volatile Map<String, Object> map = new HashMap<>();public void put(String key, Object value) {System.out.println(Thread.currentThread().getName() + "写入" + key);map.put(key, value);System.out.println(Thread.currentThread().getName() + "写入完成");}public void get(String key) {System.out.println(Thread.currentThread().getName() + "读取" + key);Object o = map.get(key);System.out.println(Thread.currentThread().getName() + "读取完成");}
}/*
1写入1
1写入完成
2写入2
2写入完成
3写入3
3写入完成
4写入4
4写入完成
5写入5
5写入完成
1读取1
1读取完成
5读取5
3读取3
3读取完成
4读取4
4读取完成
5读取完成
2读取2
2读取完成
*/

我们可以看到输出的结果在写入的时候有序的进行,读操作的时候可以无序的进行,可以看到已经到达我们预期的效果😊

10、堵塞队列

堵塞

image-20211004171202278

image-20211004171549940

image-20211004172520422

image-20211004172737902

什么情况下我们使用阻塞队列:多线程并发处理,线程池!

10.1 学会使用队列

添加、移除元素,现在有四组API

1) 四组API

方法抛出异常不会抛出异常,有返回值阻塞等待超时等待
添加add()offer()put()offer(E e, long timeout, TimeUnit unit)
移除remove()poll()take()poll(long timeout, TimeUnit unit)
判断首部element()peek()--
/*
* 抛出异常
* */public static void test1(){//队列大小3ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.add("a"));System.out.println(blockingQueue.add("b"));System.out.println(blockingQueue.add("c"));//IllegalState ExceptionQueue full  抛出异常//System.out.println(blockingQueue.add("d"));//检测队首元素System.out.println(blockingQueue.element());								                                 System.out.println("================================================");System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());//java.util.NoSuchElementException  抛出异常//System.out.println(blockingQueue.remove());}
/** 不抛出异常,有返回值* */public static void test2(){//队列大小3ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);System.out.println(blockingQueue.offer("a"));System.out.println(blockingQueue.offer("b"));System.out.println(blockingQueue.offer("c"));//falseSystem.out.println(blockingQueue.offer("d"));//检测队首元素System.out.println(blockingQueue.peek());System.out.println("================================================");System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());//nullSystem.out.println(blockingQueue.poll());}
/** 阻塞等待之☞死死的等待* */public static void test3() throws InterruptedException {//队列大小3ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);blockingQueue.put("a");blockingQueue.put("b");blockingQueue.put("c");//blockingQueue.put("d");//无检测队首元素System.out.println("================================================");System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());//System.out.println(blockingQueue.take());}
/** 等待阻塞(超时)* */public static void test4() throws InterruptedException {//队列大小3ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);blockingQueue.offer("a");blockingQueue.offer("b");blockingQueue.offer("c");blockingQueue.offer("d",2, TimeUnit.SECONDS);//无检测队首元素System.out.println("================================================");System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());blockingQueue.poll(2,TimeUnit.SECONDS);}

2) SynchronizedQueue 同步队列

没有容量,进去一个元素,必须等待取出来之后,才能再往里面放一个元素

put take

package com.zmz.queue;/*** @ProjectName: Juc* @Package: com.zmz.queue* @ClassName: SyncQueue* @Author: 张晟睿* @Date: 2021/10/8 14:18* @Version: 1.0*/import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;/*** 同步队列* 和其他的lockQueue 不一样, SynchronousQueue 不存储元素*/
public class SyncQueue {public static void main(String[] args) {SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>(); //同步队列new Thread(()->{try {System.out.println(Thread.currentThread().getName() + "put 1");synchronousQueue.put("1");System.out.println(Thread.currentThread().getName() + "put 2");synchronousQueue.put("2");System.out.println(Thread.currentThread().getName() + "put 3");synchronousQueue.put("3");} catch (InterruptedException e) {e.printStackTrace();}},"Thread1").start();new Thread(()->{try {TimeUnit.SECONDS.sleep(3);System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());TimeUnit.SECONDS.sleep(3);System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());TimeUnit.SECONDS.sleep(3);System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());} catch (InterruptedException e) {e.printStackTrace();} finally {}},"Thread2").start();}
}/*
Thread1put 1
Thread2=>1
Thread1put 2
Thread2=>2
Thread1put 3
Thread2=>3
*/

11、线程池

线程池有三大方法,七大参数,四种拒绝策略

程序的运行,本质: 占用系统的资源 ! 优化CPU资源的使用 ===>池化技术

线程池, 连接池, 内存池, 对象池///…

池化技术: 实现准备好一些资源, 有人要用,就来我这里拿,用完之后还给我

1) 线程池的好处:

  1. 降低资源消耗
  2. 提高响应速度
  3. 方便管理

线程复用,可以控制最大并发数,管理线程

2) 线程池: 三大方法

  • ExecutorService service = Executors.newSingleThreadExecutor();//单个线程
  • ExecutorService service = Executors.newFixedThreadPool(5);//创建一个固定的线程池的大小
  • ExecutorService service = Executors.newCachedThreadPool();//可伸缩的,
package com.zmz.Pool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @ProjectName: Juc* @Package: com.zmz.ThreadPool* @ClassName: ThreadPool* @Author: 张晟睿* @Date: 2021/10/8 16:44* @Version: 1.0*/
public class ThreadPool {public static void main(String[] args) {ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程ExecutorService threadPool2 = Executors.newFixedThreadPool(5); //创建一个固定的线程池的大小ExecutorService threadPool3 = Executors.newCachedThreadPool(); //可伸缩的//线程池用完必须要关闭线程池try {for (int i = 1; i <=100 ; i++) {//通过线程池创建线程threadPool3.execute(()->{System.out.println(Thread.currentThread().getName()+ " ok");});}} catch (Exception e) {e.printStackTrace();} finally {threadPool3.shutdown();}}
}

3) 七大参数

public ThreadPoolExecutor(int corePoolSize,  //核心线程池大小int maximumPoolSize, //最大的线程池大小long keepAliveTime,  //超时了没有人调用就会释放TimeUnit unit, //超时单位BlockingQueue<Runnable> workQueue, //阻塞队列ThreadFactory threadFactory, //线程工厂 创建线程的 一般不用动RejectedExecutionHandler handler //拒绝策略) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}

image-20211008170223781

image-20211008165650913

package com.zmz.Pool;import java.util.concurrent.*;/*** @ProjectName: Juc* @Package: com.zmz.Pool* @ClassName: ThreadPoolExecutorTest* @Author: 张晟睿* @Date: 2021/10/8 16:59* @Version: 1.0*/
public class ThreadPoolExecutorTest {public static void main(String[] args) {// 获取cpu 的核数int max = Runtime.getRuntime().availableProcessors();ExecutorService service =new ThreadPoolExecutor(2,//核心线程池大小max,//最大的线程池大小3,//超时了没有人调用就会释放TimeUnit.SECONDS,//超时单位new LinkedBlockingDeque<>(3),//阻塞队列Executors.defaultThreadFactory(),//线程工厂 创建线程的new ThreadPoolExecutor.AbortPolicy()//拒绝策略);try {for (int i = 1; i <= 5; i++) {service.execute(() -> {System.out.println(Thread.currentThread().getName() + "运行成功");});}}catch (Exception e) {e.printStackTrace();}finally {service.shutdown();}}
}

4) 拒绝策略

image-20211008170459374

  • new ThreadPoolExecutor.AbortPolicy() 超出最大处理线程抛出异常
  • new ThreadPoolExecutor.CallerRunsPolicy() 从哪个线程创建就由那个线程执行
  • new ThreadPoolExecutor.DiscardPolicy() 队列满了不会抛出异常
  • new ThreadPoolExecutor.DiscardOldestPolicy() 尝试去和第一个竞争,也不会抛出异常

12、四大函数式接口

新时代的程序员👨‍💻:lambda表达式、链式编程、函数式接口、Stream流式计算

image-20200812143713392

1) Function函数型接口

image-20211008172106100

package com.zmz.FourFunction;import java.util.function.Function;/*** @ProjectName: Juc* @Package: com.zmz.FourFunction* @ClassName: functionDemo* @Author: 张晟睿* @Date: 2021/10/8 17:15* @Version: 1.0*/
public class functionDemo {public static void main(String[] args) {Function<String, String> function = (str) -> {return str;};System.out.println(function.apply("Hello,zmz!"));}
}

2) Predicate 断定型接口

image-20211008172509531

package com.zmz.FourFunction;import java.util.function.Predicate;/*** @ProjectName: Juc* @Package: com.zmz.FourFunction* @ClassName: PredicateDemo* @Author: 张晟睿* @Date: 2021/10/8 17:18* @Version: 1.0*/
public class PredicateDemo {public static void main(String[] args) {Predicate<String> predicate = (str) -> {return str.isEmpty();};// falseSystem.out.println(predicate.test("zmz"));// trueSystem.out.println(predicate.test(""));}
}

3) Suppier 供给型接口

image-20211008172617885

package com.zmz.FourFunction;import java.util.function.Supplier;/*** @ProjectName: Juc* @Package: com.zmz.FourFunction* @ClassName: SuppierDemo* @Author: 张晟睿* @Date: 2021/10/8 17:21* @Version: 1.0*/
public class SuppierDemo {public static void main(String[] args) {Supplier<String> supplier = ()->{return "1024";};System.out.println(supplier.get());}
}

4) Consummer 消费型接口

image-20211008173825192

package com.zmz.FourFunction;import java.util.function.Consumer;/*** @ProjectName: Juc* @Package: com.zmz.FourFunction* @ClassName: ConsummerDemo* @Author: 张晟睿* @Date: 2021/10/8 17:21* @Version: 1.0*/
public class ConsummerDemo {public static void main(String[] args) {Consumer<String> consumer = (str)->{System.out.println(str);};consumer.accept("zmz");}
}

13、Stream 流式计算

package com.zmz.Stream;/*** @ProjectName: Juc* @Package: com.zmz.Stream* @ClassName: User* @Author: 张晟睿* @Date: 2021/10/8 18:01* @Version: 1.0*/
public class User {private int id;private String name;private int age;public User(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
package com.zmz.Stream;/*** @ProjectName: Juc* @Package: com.zmz.Stream* @ClassName: StreamDemo* @Author: 张晟睿* @Date: 2021/10/8 18:00* @Version: 1.0** * 题目要求: 用一行代码实现*  * 1. Id 必须是偶数*  * 2.年龄必须大于23*  * 3. 用户名转为大写*  * 4. 用户名倒序*  * 5. 只能输出一个用户*/import java.util.Arrays;
import java.util.List;public class StreamDemo {public static void main(String[] args) {User u1 = new User(1, "a", 23);User u2 = new User(2, "b", 23);User u3 = new User(3, "c", 23);User u4 = new User(6, "d", 24);User u5 = new User(4, "e", 25);List<User> list = Arrays.asList(u1, u2, u3, u4, u5);// lambda、链式编程、函数式接口、流式计算list.stream().filter(user -> {return user.getId()%2 == 0;}).filter(user -> {return user.getAge() > 20;}).map(user -> {return user.getName().toUpperCase();}).sorted((user1, user2) -> {return user2.compareTo(user1);}).limit(1).forEach(System.out::println);}
}

14、ForkJoin—多线并发处理框架

什么是ForkJoin?

ava.util.concurrent.ForkJoinPool由Java大师Doug Lea主持编写,它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。本文中对Fork/Join框架的讲解,基于JDK1.8+中的Fork/Join框架实现,参考的Fork/Join框架主要源代码也基于JDK1.8+。

这几篇文章将试图解释Fork/Join框架的知识点,以便对自己、对各位读者在并发程序的设计思路上进行一些启发。文章将首先讲解Fork/Join框架的基本使用,以及其中需要注意的使用要点;接着使用Fork/Join框架解决一些实际问题;最后再讲解Fork/Join框架的工作原理。

image-20211008180947714

1)ForkJoin 特点: 工作窃取!

image-20211008181432199

2)如果使用ForkJoin

第一步,通过ForkJoinPool来执行

第二步,计算任务 execute(ForkJoinTask<?> task)

第三步,计算类要去继承ForkJoinTask

ForkJoin 的计算类

ForkJoinComputer.java

package com.zmz.ForkJoin;
import java.util.concurrent.RecursiveTask;/*** @ProjectName: Juc* @Package: com.zmz.ForkJoin* @ClassName: ForkJoinComputer* @Author: 张晟睿* @Date: 2021/10/9 15:17* @Version: 1.0*/public class ForkJoinComputer extends RecursiveTask<Long> {private long start;private long end;/** 临界值 */private long temp = 1000000L;public ForkJoinComputer(long start, long end) {this.start = start;this.end = end;}/*** 计算方法* @return*/@Overrideprotected Long compute() {if ((end - start) < temp) {Long sum = 0L;for (Long i = start; i < end; i++) {sum += i;}return sum;}else {// 使用ForkJoin 分而治之 计算//1 . 计算平均值long middle = (start + end) / 2;ForkJoinComputer forkJoinDemo1 = new ForkJoinComputer(start, middle);// 拆分任务,把线程压入线程队列forkJoinDemo1.fork();ForkJoinComputer forkJoinDemo2 = new ForkJoinComputer(middle, end);forkJoinDemo2.fork();long taskSum = forkJoinDemo1.join() + forkJoinDemo2.join();return taskSum;}}
}

测试类 ForkJoinTest.java

package com.zmz.ForkJoin;import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;/*** @ProjectName: Juc* @Package: com.zmz.ForkJoin* @ClassName: ForkJoinTest* @Author: 张晟睿* @Date: 2021/10/9 15:18* @Version: 1.0*/
public class ForkJoinTest {private static final long SUM = 20_0000_0000;public static void main(String[] args) throws ExecutionException, InterruptedException {test1();test2();test3();}/*** 使用普通方法*/public static void test1() {long star = System.currentTimeMillis();long sum = 0L;for (long i = 1; i < SUM ; i++) {sum += i;}long end = System.currentTimeMillis();System.out.println(sum);System.out.println("普通程序猿——时间:" + (end - star));System.out.println("============================");}/*** 使用ForkJoin 方法*/public static void test2() throws ExecutionException, InterruptedException {long start = System.currentTimeMillis();ForkJoinPool forkJoinPool = new ForkJoinPool();ForkJoinTask<Long> task = new ForkJoinComputer(0L, SUM);ForkJoinTask<Long> submit = forkJoinPool.submit(task);Long along = submit.get();System.out.println(along);long end = System.currentTimeMillis();System.out.println("中级程序猿——时间:" + (end - start));System.out.println("--------------");}/*** 使用 Stream 流计算*/public static void test3() {long start = System.currentTimeMillis();long sum = LongStream.range(0L, 20_0000_0000L).parallel().reduce(0, Long::sum);System.out.println(sum);long end = System.currentTimeMillis();System.out.println("高级程序猿——时间:" + (end - start));System.out.println("--------------");System.out.println("============================");}
}

image-20211009152827573

分析一下高级程序猿的处理:

image-20211009152915075

.parallel().reduce(0, Long::sum)使用一个并行流去计算整个计算,提高效率。

❤️‍❤️‍❤️‍最后(学妹照片)

附一张学妹的照片

image-20211009151426415

⭐学妹都已经收藏了!!!⭐


http://www.ppmy.cn/news/867031.html

相关文章

排兵布阵问题java语言_hdu 4539 郑厂长系列故事——排兵布阵

郑厂长系列故事——排兵布阵 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1338 Accepted Submission(s): 478 Problem Description 郑厂长不是正厂长 也不是副厂长 他根本就不是厂长 事实上 他是带兵打仗的…

郑厂长系列故事——体检

郑厂长不是正厂长   也不是副厂长   他根本就不是厂长   只是公司的一个码农      郑厂长所在的腾讯公司每一年都要组织员工体检&#xff0c;比如量身高体重、测血压之类的&#xff0c;今年也不例外。   这次总共有N位员工接受体检&#xff0c;并且每个员工都需要做…

c语言在多个数数最大数,求多个数的最大公因数算法 C语言

我们用(a1,a2,....)表示最大公因数 [a1,a2,.....]表示最小公倍数 1、两个数的最大公因数 辗转相除法&#xff0c;可以直接使用C语言自带的 c __gcd(a&#xff0c;b)&#xff1b; 辗转相除法原理可以自行百度。 2、多个数以上的最大公因数 1、多次辗转相除法 1.使用辗转相除法…

算法题_聪明的厂长

题目&#xff1a; 厂长阿雄通过每个员工的劳动技能等级来分配每天的工作。一个工作任务只能由劳动技能等级大于等于任务难度的员工来完成&#xff0c;且同一天里一个员工只能对应一个工作任务。一个工作任务只能由一个员工来完成。求出所有可能的分配方式。 输入&#xff1a; …

【HCIA】07.OSPF

动态路由的协议分类 按工作区域分&#xff1a; IGP&#xff08;内部网关协议 interior gateway protocols&#xff09;&#xff1a;OSPF、IS-IS、RIPEGP&#xff08;外部网关协议 exterior gateway protocols&#xff09;&#xff1a;BGP 按工作机制及算法分类&#xff1a; 距离…

python re.findall和re.search同样的正则表达式,为什么规则不一样??

今天遇到一个问题&#xff0c;在使用python的re.findall和re.search的过程中&#xff0c;发现一个奇怪的事情&#xff0c;同样的表达式&#xff0c;两者的表现却不一样&#xff0c;例如下述代码&#xff1a; s "gpdk090_nmos1v #(.w(1.5e-6), .l(2.8e-07), .as(9e-13), …

百度网盘打不开解决方案

命令行输入&#xff1a;rm -rf ~/baidunetdisk

电磁场与电磁波(1)——简史

一、春秋战国时期&#xff0c;已经有定性观察 影子理论&#xff1a;墨子在《墨经》中探讨了光与影子的关系&#xff0c;他提出了“景不徙”的观点&#xff0c;墨子认为影子本身是不会移动的&#xff0c;只有物体和光源才会造成影子的移动&#xff0c;并且提出了影子的大小和光源…

电脑百度网盘打不开怎么办 电脑百度网盘双击没反应处理方法

有时候我们想要在电脑浏览器上下载一些文件时&#xff0c;打开的文件下载链接有些需要通过百度网盘来存储下载&#xff0c;然而当用户在电脑中安装完百度网盘工具之后&#xff0c;双击想要打开时却总是没反应&#xff0c;对此电脑百度网盘打不开怎么办呢&#xff1f;接下来小编…

经典回顾丨同为科技(TOWE)在2008年奥运场馆防雷建设中都做了什么?

针对大型体育赛事场馆防雷建设工作非常重要&#xff0c;这是因为大型体育赛事通常吸引了大量的观众和运动员聚集&#xff0c;一旦场馆遭受雷击&#xff0c;可能会造成严重的伤亡和财产损失。如今&#xff0c;大型体育赛事的场馆都会配备防雷设施&#xff0c;如建筑物避雷针、接…

2. CSS3的新特性

2.1CSS3的现状 ●新增的CSS3特性有兼容性问题, ie9才支持 ●移动端支持优于PC端 ●不断改进中 ●应用相对广泛 ●现阶段主要学习: 新增选择器和盒子模型以及其他特性 CSS3给我们新增了选择器,可以更加便捷,更加自由的选择目标元素&#xff1a; 1.属性选择器 2.结构伪类选择器…

百度网盘打不开

Mac打不开百度网盘网页版和客户端 1.网页版处理方法2. 客户端处理方法(网页版通用,推荐使用) 1.网页版处理方法 把链接地址中pan 改成 yun, 刷新就可以打开了 2. 客户端处理方法(网页版通用,推荐使用) 打开终端&#xff0c;修改host的文件 sudo vim /etc/hosts在文件最后添…

大学生用一周时间给麦当劳做了个App(安卓版)

背景 有个大学生粉丝最近私信联系我&#xff0c;说基于我之前开源的多语言项目做了个仿麦当劳的项目&#xff0c;虽然只是个样子货&#xff0c;但是收获颇多&#xff0c;希望把自己写的代码开源出来供大家一起学习进度。这个小伙伴确实是非常积极上进&#xff0c;很多大学生&a…

【学习笔记】在Android使用Frida进行https抓包

最近需要在Android进行https抓包&#xff0c;对数据解密&#xff0c;找了很多方法&#xff0c;终于成功了&#xff0c;不过原文一些步骤对于我这个小白还是有点不理解的地方&#xff0c;在此记录一下。 1. 前提条件 一台root手机frida环境 2. frida环境搭建 该步骤全程参考&…

4. Bond

文章目录 1. Corporate Bonds1.1 Introduction of Bonds1.1.1 Definition1.1.2 Basic Features1.1.3 Cash Flow Structure of A Plain Vanilla Bond1.1.4 Bond Price 1.2 Bond Markets1.2.1 Bond Issuance1.2.2 Bond Trading1.2.3 Classification of Bonds 1.3 Bond Indenture1…

牛客练习赛30-A/C

链接&#xff1a;https://ac.nowcoder.com/acm/contest/216/A来源&#xff1a;牛客网 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32768K&#xff0c;其他语言65536K 64bit IO Format: %lld 题目描述 众所周知&#xff0c;小K是nowcoder的暴…

[自动驾驶]Build a Traffic Sign Recognition Program

看《准确率98%的深度学习交通标志识别是如何做到的?》这篇文章的时候,发现了udacity的自动驾驶课程。可惜要收费,不过课程project在github上有,那直接做project就好了,不上课了。 那先从Build a Traffic Sign Recognition Program开始吧。 环境准备 官方提供了CPU的doc…

Docker 镜像与容器存储目录结构精讲

很多朋友在初学 docker 的时候非常迷茫&#xff0c;不清楚 docker 是怎样的一种存储方式&#xff0c;并且也不清楚 docker 到底存储在什么地方。其实 docker 的镜像与容器都存储在 /var/lib/docker 下面&#xff0c;那么基于不同的系统又有不同的存储方式&#xff0c;在 ubuntu…

“glibc detected”, free(), invalid pointer解决方法

在运行的时候出现了这个错误&#xff1a; *** glibc detected *** /home/zyj/zk_lock/.libs/lt-zklocktest: free(): invalid pointer: 0x00000000004106d0 *** 开始啥都不明白&#xff0c;只是觉得哪里的free估计除了问题&#xff0c;在网上查了一系列资料后&#xff0c;开…
最新文章