JAVA中的线程、死锁、异常

线程

Thread

  • 一、程序
    • 1.一段静态代码(静态)
  • 二、进程
    • 1.动态的,有开始,有结束;
    • 2.程序的一次执行过程,
    • 3.操作系统调度分配资源的最小单位;
  • 三、线程
    • 1.进程细化为线程
    • 2.内部的一条执行路径;
    • 3.多线程,
    • 4.CPI调度、分配的最小单位;
    • 5.多线程间可以通信,一个进程共享一个堆;(会有安全问题);
    • 6.每个进程有一个独立的内存空间;
    • 7.线程调度
      • (1)分时调度;(平均分配每个时间)
      • (2)抢占式调度;(java);提高响应,设置优先级;

并行:

  • 1、多个事件,同一时间发生;
  • 2、多条指令在多个cpu上同时执行;(多核)
  • 3、三个大厨在炒菜;

并发:

  • 1、多个事件,在同一个时间段内发生;(同一时刻可能只有一个)
  • 2、Cpu快速切换处理;
  • 3、一个大厨在炒三个菜;

线程:java.lang.Thread

  • 1、创建:
    • (1)继承thread类
      • ①创建子类继承Thread,
      • ②重写run方法
      • ③创建对象
      • ④调用start方法;
        • 1)启动线程
        • 2)调用当前线程的run方法;
        • 3)结束前不能继续调start;不能让已经start的线程继续start否则报异常;
      • ⑤多个线程间的执行没有冲突,同时执行;

例1

class F extends Thread {@Overridepublic void run() {System.out.println(1);}
}

例2

class H extends Thread {static Object obj = new Object();static int total = 100;@Overridepublic void run() {/* 同步代码块 *//* 使用static修饰后可以保证obj的唯一性 */synchronized (obj) {H.total--;System.out.println(H.total);}/*此处this不能保证唯一性/慎用*/synchronized (this) {H.total--;}synchronized (Window.class) {H.total--;}synchronized (H.class) {H.total--;}}
}

例3

public class ThreadTest {@Testpublic void test(){A a = new A();a.start(); //开始创建新线程;/* 还是主线程 */for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + ": " + i);}A a2 = new A();a2.start();/* 匿名对象 */new Thread(() -> {for (int i = 0; i < 10; i++) {if(i%2==0) {System.out.println(Thread.currentThread().getName() + ": " + i);}}}).start();}
}class A extends Thread {@Overridepublic void run() {for (int i = 0; i < 10; i++) {if(i%2==0) {System.out.println(Thread.currentThread().getName() + ": " + i);}}}
}
  • (2)实现Runnable接口
    • ①创建一个实现类
    • ②实现接口内的抽象run方法
    • ③创建对象
    • ④将对象作为参数,传入Thread构造器;创建实例
    • ⑤创建实例后,调用start方法;
class J implements Runnable{int i = 100;@Overridepublic void run() {
//        synchronized (J.class){
//            method();
//        }i--;}public void method() {i--;}/* 同步方法 */public synchronized void method2() {i--;}
}
public class ThreadTest2 {public static void main(String[] args) {B b = new B();
//        new Thread(b){}.start();Thread t = new Thread(b);t.start();for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+ ": " + i);}Thread t2 = new Thread(b);t2.start();/* 有问题的写法? */new Thread(b){@Overridepublic void run() {for (int i = 6; i < 10; i++) {System.out.println(Thread.currentThread().getName()+ ": " + i);}}}.start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+ ": " + i);}}}).start();}
}
class B implements Runnable {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+ ": " + i);}}
}
public class ThreadTest3 {public static void main(String[] args) throws InterruptedException {D d = new D();Thread t = new Thread(d);t.setName("子线程");t.setPriority(Thread.MIN_PRIORITY);t.start();Thread.currentThread().setName("主线程");for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + ": " + i);if(i == 3) {t.join();}System.out.println(Thread.currentThread().getPriority());}}
}class D implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "_" + Thread.currentThread().getPriority() + ": " + i);if(i % 3 == 0) {
//                Thread.yield();}}}
}

建议:

  • 1、建议使用Runnable 方式
    • (1)避免了类的单继承性的局限性
    • (2)更适合处理有共享数据的情况

联系:

  • 1、Thread 类 本来也是实现的Runnable的方法;

常用方法:

  • 1、start
  • 2、Run:线程内主要需要的任务
  • 3、currenctThread(): 获取当前线程
  • 4、getName(): 获取线程的名称;
  • 5、SetName: 设置线程名称
  • 6、Sleep(ms): 静态方法:
    • (1)当前线程休眠指定毫秒数;
    • (2)会抛出异常;
  • 7、Yield();静态方法
    • (1)主动释放cpu的执行权
    • (2)Cpu可能去执行其他的线程;
    • (3)也可能很快继续分配回来;
  • 8、Join(); 在线程A中通过线程B调用join方法;之后线程A被阻塞,直到B执行结束;
  • 9、isAlive(); 线程是否存活
  • 10、过时方法:stop,强行结束一个线程,使其死亡。不建议使用;
  • 11、Suspend/resume; 操作失误可能造成死锁,不建议使用;
    • (1)Suspend: 暂停
    • (2)Resume:继续;

生命周期:

  • 1、Jdk1.5之前

    • (1)在这里插入图片描述
  • 2、Jdk 1.5 及之后

    • (1)在这里插入图片描述

    • (2)阻塞分的更细了

    • (3)可以查看Thread的enum枚举类State;

优先级:

  • 1、getPriority(); 获取优先级;
    • (1)默认级别都是5;
    • (2)最低的是1,最高的是10;
  • 2、THread 内部常量:
    • (1)MIN_PRIORITY: 1;
    • (2)MAX_ : 10
    • (3)NORMAL_ 5;
  • 3、setPriority(): 设置优先级;
    • (1)设置完之后不一定是哪个优先
    • (2)内部有cpu等规则;
  • 4、

线程安全

使用线程的同步机制

1、同步代码块

* (1)synchronized(同步监视器) {* ①需要被同步的代码* ②被操作的共享数据;
* };
  • ******代码块被视为一个整体,使用syncxxx包裹后,一个线程结束后。另一个线 程才能执行;
  • (2)同步监视器
  • ①俗称锁;
  • ②可以使用任何一个类的对象充当;
  • ③多个线程,必须公用同一个同步监视器;
  • ④这个对象必须是唯一的;可以尝试使用this;
  • ⑤可以使用Window.class;
  • ⑥可以使用当前类.class;
  • (3)Ctrl+alt+t

2、同步方法;

  • (1)S 如果操作共享数据的代码,在一个方法中
  • (2)直接给方法添加修饰符:synchronzied;
  • (3)非静态同步监视器默认就是this;(不可修改)
    • ①此时考虑this是否唯一;
  • (4)如果可以改成静态方法,可以考虑使用静态方法;
    • ①默认的监视器是当前类.class;
  • (5)如果this不唯一;
    • ①类声明多个实例的情况会有不唯一的情况;
  • (6)
public class WaitTest {public static void main(String[] args) {WaitTest wt = new WaitTest();wt.method();}public synchronized void method(){System.out.println(1);try {this.wait(1000);System.out.println(3);} catch (InterruptedException e) {e.printStackTrace();}this.notify();System.out.println(2);}//wait 中添加了时间之后打印顺序: 1-3-2;// wait 中不添加时间的话,只打印1;
}

推荐使用implements Runnable;方式;

5.0新特性:Lock

public class LockTest {private static final ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {}public void  method() {try {lock.lock();new Thread(){@Overridepublic void run() {System.out.println(1);}}.start();} finally {lock.unlock(); //为保证unlock被执行,放到finally中;}}
}

指令重排?是什么

  • 1、volatile 修饰符避免
  • 2、Volatile A a= new A();

死锁

  • 1、互相抢占资源,等待对方释放;
  • 2、每人一个监视器,等待对方释放监视器
  • 3、拿不到监视器,对面不释放;
  • 4、见代码:DeadLockTest.java; 加上sleep后可以高概率复现死锁;
public class DeadLockTest {public static void main(String[] args) {StringBuilder s1 = new StringBuilder();StringBuilder s2 = new StringBuilder();new Thread(){@Overridepublic void run() {synchronized (s1){s1.append("a");s2.append("1");/* 加上sleep之后1秒之内不会释放,另一个线程等着用s1;这个线程等着用s2 */try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (s2){s1.append("b");s2.append("2");}System.out.println(s1);System.out.println(s2);}}}.start();new Thread(){@Overridepublic void run() {synchronized (s2){s2.append("-3");s1.append("-c");synchronized (s1){s2.append("4");s1.append("d");}System.out.println(s1);System.out.println(s2);}}}.start();}
}

如何看待:

  • 1、避免;

原因及解决避免:(破坏死锁的形成条件)

  • 1、互斥条件:=>
    • (1)无法处理;
  • 2、占用且等待: =>
    • (1)一次性拿到所有资源;
  • 3、不可抢夺: =>
    • (1)申请不到资源时,主动释放资源;
  • 4、循环等待: =>
    • (1)改为线性顺序;排号;

Lock锁:

  • 1、解决线程安全;
  • 2、JUC:=> java.util.concurrent;
  • 3、Private static [final] ReentrantLock lock = new RenntrantLock();
  • 4、lock.lock();
    • (1)可能不安全的逻辑;
  • 5、lock.unlock(); => 必须要保证一定会执行;
  • Lock锁定对共享资源的调用;
  • Lock好过synchronized;lock不需要包上正片代码

线程通信

一、两个线程,交替打印12345678.。。

  • 1.See the code;
    • Wait();
  • 1、wait(); //进入等待并释放对同步监视器的调用;而sleep不会释放;
  • 2、Notify(); //唤醒wait;
    • (1)只能唤醒一个
    • (2)唤醒被wait中优先级最高的
    • (3)如果优先级相同,则随机唤醒;
    • (4)然后被唤醒的,继续上次被wait的地方继续执行;
  • 3、NotifyAll(): 唤醒所有wait的线程;
public class CommunicationTest {public static void main(String[] args) {Q q = new Q();Thread t1 = new Thread(q);Thread t2 = new Thread(q);t1.start();t2.start();}
}
class Q implements Runnable {static Object obj = new Object();private static int count = 100;@Overridepublic void run() {while (true) {synchronized (obj) {   // 因为和notify和wait的调用者不一致了;//                notify(); //唤起waitobj.notify(); //唤起waitif (count > 0) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ": " + count);count--;try {obj.wait(); //进入等待并释放对同步监视器的调用;} catch (InterruptedException e) {e.printStackTrace();}} else {break;}}}}
}
/* 实现两个线程交替打印 */
//class Q implements Runnable {
//    static Object obj = new Object();
//    private static int count = 100;
//
//    @Override
//    public void run() {
//        while (true) {
//            synchronized (this) {   //此处除了使用this,使用其他的都会报错;因为和notify和wait的调用者不一致了;
//
                notify(); //唤起wait
//                this.notify(); //唤起wait
//
//                if (count > 0) {
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//
//                    System.out.println(Thread.currentThread().getName() + ": " + count);
//                    count--;
//
//                    try {
//                        wait(); //进入等待并释放对同步监视器的调用;
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//
//                } else {
//                    break;
//                }
//            }
//
//
//        }
//    }
//}//class Q implements Runnable {
//    private  static  int count = 100;
//    @Override
//    public void run() {
//        while (count > 0) {
//            try {
//                Thread.sleep(10);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            synchronized (Q.class){
//                System.out.println(Thread.currentThread().getName() +": "+count);
//                count--;
//            }
//        }
//    }
//}

使用:

  • 1、必须用在同步代码块,或者同步方法中;(synchronized)
  • 2、不能和lock搭配使用;
  • 3、Lock需要配合condition通信(更灵活);
  • 4、监视器必须和wait和notify的调用者一致;

创建线程

  • 1、Callable: 5.0新增;
/*** @Date 2023/8/3 14:51* @Discrition  非完全代码;callable 需要结合 futureTask 来使用;*/
public class ClassableTest {public static void main(String[] args) {W w = new W();w.call();
//        try {
//            w.call();
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }}
}class W implements Callable {@Overridepublic Object call() {synchronized (W.class) {System.out.println(1);}return null;}//    public Object call() throws Exception {
//        synchronized (W.class) {
//            System.out.println(1);
//        }
//        return null;
//    }
}
  • 2、线程池:生产中使用;

线程池:

  • 1、先创建好多个空线程,等待任务来了执行;可以复用;
public class ThreadPondTest {public static void main(String[] args) {
//        ThreadPoolExecutor executor = new ThreadPoolExecutor();}
}class R {}

异常

Throwable两个子类:

1、Error

  • (1)处理方式:只能改代码;(jvm资源耗尽,无法处理)
  • (2)错误类型:
    • ①Stack Overflow Error;栈溢出
    • ②OutOfMemoryError;堆内存移除;==>OOM

2、Exception

  • (1)可以处理,通过代码catch让程序继续执行;
  • (2)区分:
    • ①Java~运行时异常:只有一个(runtimeException=>扩展开还有很多)
    • ②Javac~编译时异常

Exception:

  • 1、将无线重复的ifelse=》改为。。。
  • 2、将所有可能报错的放在一起处理下;
public class ThrowsTest {@Testpublic void test(){try {ThrowsTest.method1();}finally {System.out.println(1);}System.out.println(2);}public static void method1() throws OutOfMemoryError{int[] arr = new int[] {1,2};System.out.println(arr[2]);System.out.println(3);}@Testpublic void test2(){new B();}
}
class A {void method1() throws NullPointerException{}
}
class B extends A{void method1(){}
}

处理方式:

方式一 try-catch-finally(抓抛模型)**

1、自定义逻辑

  • (1)抛出: 产生异常对象,抛出;
  • (2)抓:捕获并处理,处理后代码可以继续执行;
  • (3)Finally 无论什么情况,代码块内都会执行;

2、printStackTrace (最常用-推荐)打印堆栈信息

  • (1)1111
  • 3、
  • 4、
  • 5、
  • 6、 运行时异常不做处理,主要处理编译时异常;

Catch结构顺序:

  • 1、如果有多个catch结构,其中的异常类型无子父类关系则无顺序
  • 2、如果有子父类关系,则父类要放到后面;

Finally:

  • 1、在catch还存在异常的话,后面的代码不放到finally中的话不会被执行;
  • 2、一定要被执行的语句,放到finally中;
  • 3、Finally比catch先执行;
  • 4、Finally比try中先执行;

System.exit(0); 虚拟机强行结束;

方式二

  • 1、Throws
  • 2、格式:
    • (1)Throws 类型1, 类型2 。。。 ;
    • (2)Public void test() throws NullxxxxException{}
  • 3、是否解决了异常
    • (1)向上抛出,不算真正解决;需要调用者来继续处理;

继承:

  • 1、父类方法使用了throws,子类的方法如果也使用throws则必须为同类型异常,或子类异常,可以不是用throws;
  • 2、RuntimeException 这个范围类型写了没用;
  • 3、如果父类的方法没有抛出异常,则子类方法中不能抛出异常;

手动抛出异常:throw;

  • 1、throw new Object(“description”);
public class ThrowsTest {@Testpublic void test(){try {ThrowsTest.method1();}finally {System.out.println(1);}System.out.println(2);}public static void method1() throws OutOfMemoryError{int[] arr = new int[] {1,2};System.out.println(arr[2]);System.out.println(3);}@Testpublic void test2(){new B();}
}
class A {void method1() throws NullPointerException{}
}
class B extends A{void method1(){}
}

自定义异常

  • 1、创建类继承自某个异常类;
  • 2、通常继承自 RuntimeException 或者Exception;
public class DIYException extends RuntimeException{
}
  • 3、空参构造器
  • 4、形参构造器
  • 5、常量(序列版本号);
  • 6、,即可抛出
public class ManuThrowTest {int i = 1;@Testpublic void test(){this.i = 0;this.method1();}public void method1(){if(this.i > 0) {}else {throw new  NullPointerException("ghjg");}}public void method2() throws Exception {throw new Exception("123"); //必须搭配处理;(因为是编译时错误)}public void method3() {throw new DIYException(); //自定义异常类;}
}

为什么要自定义?

  • 1、见名知意;
  • 2、已有类型不足以见名知意;

~~~~运行时异常可以不处理,编译时异常必须要处理;或trycatch或throws~~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3015125.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

循环编码:时间序列中周期性特征的一种常用编码方式

在深度学习或神经网络中&#xff0c;“循环编码”&#xff08;Cyclical Encoding&#xff09;是一种编码技术&#xff0c;其特点是能够捕捉输入或特征中的周期性或循环模式。这种编码方法常用于处理具有周期性行为的任务&#xff0c;比如时间序列预测或理解展示周期性特征的序列…

函数编辑器调研及设计开发

前言&#xff1a;在产品研发中需要一款可嵌入web开发的代码及函数编辑器&#xff0c;本文从功能&#xff0c;扩展&#xff0c;外观/交互&#xff0c;维护/社区&#xff0c;兼容性&#xff0c;开源与否等方面考虑&#xff0c;进行对比筛选 1、编辑器统计数据 市面上编辑器有很…

软考是否存在包过班?

国家考试&#xff0c;虽然有人喊着包过&#xff0c;但你也别轻易相信啊&#xff0c;姐妹&#xff0c;要好好保护好你的钱包啊&#xff01;这种考试是没有所谓的包过的。 给你一些学习软考需要注意的要点&#xff1a; 1、深入理解考试内容&#xff1a; 在准备软考之前&#xf…

【redis】redis持久化分析

目录 持久化Redis持久化redis持久化的方式持久化策略的设置1. RDB&#xff08;快照&#xff09;fork(多进程)RDB配置触发RDB备份自动备份手动执行命令备份&#xff08;save | bgsave&#xff09;flushall命令主从同步触发动态停止RDB RDB 文件恢复验证 RDB 文件是否被加载 RDB …

面试中算法(删去n个数字后的最小值)

有一个整数&#xff0c;从该整数中去掉n个数字&#xff0c;要求剩下的数字形成的新整数尽可能小。 分析&#xff1a;使用栈的特性&#xff0c;在遍历原整数的数字时&#xff0c;让所有数字一个一个入栈&#xff0c;当某个数字需要被删除时&#xff0c;&#xff08;即栈顶数字&g…

期权扫盲贴:基础知识汇总,如何开通低佣期权账户(建议收藏)

一、什么是场内期权&#xff1f; 场内期权&#xff0c;也被称为交易所期权&#xff0c;是指在证券交易所内进行交易的标准化期权合约。 场内期权的交易是由证券交易所发布和监管的&#xff0c;具有统一的合约规格和交易规则&#xff0c;因此方便投资者进行交易。 以中国证券…

智慧公厕建设,打造智慧城市基础设施新亮点

公共厕所是城市基础设施的重要组成部分&#xff0c;而智慧公厕的建设则是现代城市管理的创新之举。为了实现公厕的精细化管理和提供更便捷的服务&#xff0c;推进智慧公厕建设必须要实现技术融合、业务融合、数据融合的目标&#xff0c;跨越层级、地域、系统、部门和业务的限制…

【C语言】——联合体与枚举

【C语言】——联合体与枚举 一、联合体1.1、联合体类型的声明1.2、联合体的特点1.3、相同成员的结构体和联合体对比1.4、联合体的大小计算1.5、联合体的应用举例 二、枚举2.1、枚举类型的声明2.2、枚举类型的优点 一、联合体 1.1、联合体类型的声明 联合体也叫做共用体   与…

每日OJ题_贪心算法三②_力扣553. 最优除法

目录 力扣553. 最优除法 解析代码 力扣553. 最优除法 553. 最优除法 难度 中等 给定一正整数数组 nums&#xff0c;nums 中的相邻整数将进行浮点除法。例如&#xff0c; [2,3,4] -> 2 / 3 / 4 。 例如&#xff0c;nums [2,3,4]&#xff0c;我们将求表达式的值 "…

冲突:故事型游戏的燃料

在故事型游戏中&#xff0c;冲突是推动情节发展的关键因素。没有冲突&#xff0c;故事就会变得平淡无奇&#xff0c;缺乏吸引力。在这篇博客中&#xff0c;我将探讨冲突在故事型游戏中的重要性&#xff0c;以及如何利用冲突为游戏增色添彩。 首先&#xff0c;让我们来了解一下冲…

【Ajax零基础教程】-----第一课 Ajax简介

一、什么是ajax ajax即 Asynchronous javascript And XML (异步 javaScript 和 XML) 是一种创建交互式&#xff0c;快速动态应用的网页开发技术&#xff0c;无需重新加载整个网页的情况下&#xff0c;能够更新页面局部数据的技术。 二、为什么使用Ajax 通过在后台与服务器进行少…

水表集中抄表器是什么?什么叫水表集中抄表器?

1.简述 水表集中抄表器是一种智能化的智能设备&#xff0c;主要运用于高效率、清晰地收集管理方法住户或商业客户的用水数据信息。它摒弃了传统的人工抄表方法&#xff0c;完成了远程控制全自动抄表&#xff0c;大大提高了水务管理的效率和精确性。 2.功能特点 2.1实时数据分…

抖音短视频矩阵系统技术源头/源代码开发部署/SaaS贴牌/源码api代开发

抖音短视频矩阵系统技术源头/源代码开发部署/SaaS贴牌/源码官方平台api授权代开发 一、短视频矩阵系统源码开发步骤 短视频矩阵系统的源头开发步骤通常包括以下几个关键阶段&#xff1a; 1.需求分析&#xff1a;明确系统的目标用户、功能需求、性能要求等。 2.系统设计&…

网络机顶盒哪个好?2024畅销网络机顶盒排行榜

因买网络机顶盒踩雷的人不在少数&#xff0c;许多不懂网络机顶盒哪个好的消费者在挑选时会参考网络机顶盒排行榜&#xff0c;这次小编带来了业内最新发布的热销网络机顶盒排行榜&#xff0c;想买网络机顶盒可以看看入围的以下品牌&#xff0c;是目前最受消费者欢迎的品牌。 一&…

python菜鸟级安装手册-上篇

python安装教程 电脑-右键-属性&#xff0c;确认系统类型和版本号&#xff0c;比如本案例系统是64位 win10 点击python官网&#xff0c;进行下载 适用于 Windows 的 Python 版本 |Python.org 选择第一个安装程序64位即可满足需要&#xff0c; 嵌入式程序包是压缩包版本&…

19.删除链表的倒数第N个结点

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#xff1a;…

纯血鸿蒙APP实战开发——自定义安全键盘案例

介绍 金融类应用在密码输入时&#xff0c;一般会使用自定义安全键盘。本示例介绍如何使用TextInput组件实现自定义安全键盘场景&#xff0c;主要包括TextInput.customKeyboard绑定自定义键盘、自定义键盘布局和状态更新等知识点。 效果图预览 实现思路 1. 使用TextInput的cu…

借势母亲节h5小游戏的作用是什么

企业商家往往喜欢借势节日开展营销&#xff0c;母亲节作为5月的重要节日自然不可错过&#xff0c;不同行业商家都有自己开展互动想要实现的效果&#xff0c;如品牌宣传曝光、引流及渠道跳转等。 基于微信社交属性&#xff0c;有利于品牌发展&#xff0c;在【雨科】平台拥有多款…

stm32和树莓派的区别?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「stm32的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;Stm32和树莓派是两个不同的领域…

MyCat安装

MyCat安装 官网下载地址打不开说明采用站点的方式进行下载基础包 &#xff1a;程序包&#xff1a; 配置原型库数据源root.user.json 配置文件说明&#xff08;默认配置&#xff09; Mycat启动授权启动mycat启动mycat查看mycat日志连接Mycat 官网下载地址打不开说明 官网可能受…