首页
统计
关于
Search
1
Sealos3.0离线部署K8s集群
1,085 阅读
2
类的加载
742 阅读
3
Spring Cloud OAuth2.0
726 阅读
4
SpringBoot自动装配原理
691 阅读
5
集合不安全问题
586 阅读
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Linux
容器
Docker
Kubernetes
Python
FastApi
登录
Search
标签搜索
Java
CSS
mysql
RabbitMQ
JavaScript
Redis
JVM
Mybatis-Plus
Camunda
多线程
CSS3
Python
Spring Cloud
注解和反射
Activiti
工作流
SpringBoot
Mybatis
Spring
html5
蘇阿細
累计撰写
389
篇文章
累计收到
4
条评论
首页
栏目
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Linux
容器
Docker
Kubernetes
Python
FastApi
页面
统计
关于
搜索到
157
篇与
的结果
2020-11-27
反射
动态语言在运行时可以改变其结构的语言,即在运行时代码可以根据某些条件改变自身结构主要的动态语言有:Object-C、C#、JavaScript、PHP、Python等静态语言与动态语言相反,如:C、C++、Java等Java具有一定的动态性,即反射机制获取类似动态语言的特性Java Reflection(反射)Reflection是Java被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。Class c = Class.forName("java.lang.String")加载完类之后,在堆内存的方法中就产生了一个Class类型的对象,这个对象就包含了完整的类的结构信息。可以通过这个对象看到类的结构——反射。正常方式:引入需要的”包类“名称 --->通过new实例化 --->取得实例化对象反射方式:实例化对象 --->getClass()方法 --->得到完整的”包类“名称package com.sw.reflection; /** * @Author suaxi * @Date 2020/11/27 15:58 */ public class Test01 extends Object{ public static void main(String[] args) throws ClassNotFoundException { //通过反射获取类的Class对象 Class<?> c1 = Class.forName("com.sw.reflection.Test01"); System.out.println(c1); //一个类在内存中只有一个Class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 Class<?> c2 = Class.forName("com.sw.reflection.Test01"); Class<?> c3 = Class.forName("com.sw.reflection.Test01"); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); } } //实体类 class User{ int id; String name; int age; public User() { } 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; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
2020年11月27日
62 阅读
0 评论
0 点赞
2020-11-27
Class类
在Object类中定义了以下方法,此方法将被所有子类继承public final Class getClass()以上的方法返回的类型是一个Class类,是Java反射的源头Class本身也是一个对象Class对象只能由系统创建一个加载的类在JVM中只会有一个Class实例一个Class对象对应的是一个加载到JVM中的一个.class文件每个类的实例都会记得自己是由哪一个Class生成的通过Class可以完整的得到一个类中的所有被加载的结构Class类是Reflection的根源Class类的常用方法方法名说明static ClassforName(String name)返回指定类名name的对象Object newInstance()调用缺省构造函数,返回Class对象的一个实例getName()返回此Class对象所表示的实体的名称Class getSuperClass()返回当前Class对象的父类的Class对象Class[] getinterfaces()返回当前Class对象的接口ClassLoader getClassLoader()返回该类的类加载器Constructor[] getConstructors返回一个包含某些Constructor对象的数组Method getMethod(String name,Class.. T)返回一个Method对象,此对象的形参类型为paramTypeField[] getDeclaredFields()返回Field对象的一个数组获取Class类的实例1、若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高Class c = Person.class;2、已知某个类的实例,调用该实例的getClass()方法获取Class对象Class c = person.getClass();3、已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException异常Class c = Class.forName("com.sw.xxx.xx");4、内置基本数据类型可以直接用类名.TYPE5、还可以用ClassLoader获取package com.sw.reflection; /** * @Author suaxi * @Date 2020/11/27 16:17 * Class类的创建方式 */ public class Test02 { public static void main(String[] args) throws ClassNotFoundException { Person p = new Student(); System.out.println("孙笑川是"+p.getName()); //方式一:通过对象获得 Class c1 = p.getClass(); System.out.println(c1.hashCode()); //方式二:forname获得 Class c2 = Class.forName("com.sw.reflection.Student"); System.out.println(c2.hashCode()); //方式三:通过类名.class获得 Class c3 = Student.class; System.out.println(c3.hashCode()); //方式四:基本内置类型的包装类都以一个Type属性 Class c4 = Integer.TYPE; System.out.println(c4); //获得父类类型 Class c5 = c1.getSuperclass(); System.out.println(c5); } } class Person{ String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person{ public Student() { this.name = "学生"; } }
2020年11月27日
47 阅读
0 评论
0 点赞
2020-11-27
自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口@interface用来声明一个注解,格式:public @interface 注解名{定义的内容}其中的每一个方法实际上是声明了一个配置参数方法的名称就是参数的名称返回值类型就是参数的类型(返回值只能说基本类型Class、String、int等)可以通过default来声明参数的默认值如果只有一个参数成员,参数名一般设置为value注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值package com.annotation.demo01; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Author suaxi * @Date 2020/11/27 11:10 * 自定义注解 */ public class Test01 { //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值 @MyAnnotation(name = "孙笑川",schools = {"xx大学,xx小学"}) public void test(){ } //@MyAnnotation2(value = "药水哥") @MyAnnotation2("药水哥")//注解中默认值为value的时候value可以省略不写 public void test2(){ } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation{ //注解的参数:参数类型 + 参数名() String name() default ""; int age() default 0; int id() default -1; //如果默认值为-1,表示不存在 String[] schools(); } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //如果只有一个参数成员,参数名一般设置为value String value(); }
2020年11月27日
61 阅读
0 评论
0 点赞
2020-11-26
线程池
线程池Jdk 5起提供了线程池相关的API:ExecutorService和ExecutorExecutorService:真正的线程池接口,常见子类:ThreadPoolExecutorvoid executor(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable Future submit(Callable task):执行任务,有返回值,一般用来执行callablevoid shutdown():关闭连接池Executors:工具类,线程池的工厂类,用于创建并返回不同类型的线程池package com.thread.threadDemo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @Author suaxi * @Date 2020/11/26 22:00 * 线程池 */ public class TestPool { public static void main(String[] args) { //1、创建线程池 //newFixedThreadPool 线程池大小 ExecutorService service = Executors.newFixedThreadPool(10); //2、执行 service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); //3、关闭连接 service.shutdown(); } } class MyThread implements Runnable{ @Override public void run() { System.out.println("线程池测试"); } }
2020年11月26日
84 阅读
0 评论
0 点赞
2020-11-26
Lock(锁)
Lock(锁)从Jdk5开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步(同步锁使用Lock对象充当)java.util.concurrent.locks.ReentrantLock接口是控制多个线程对共享资源进行访问的工具;锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显示加锁,释放锁使用方法:class A{ //定义锁 private final ReentrantLock lock = new ReentrantLock(); public void method() { lock.lock(); //加锁 try { //保证线程安全的代码 }finally { lock.unlock(); //解锁 //如果同步代码有异常,要将unlock()写入finally语句块 } } } }购票实例:package com.thread.threadDemo; import java.util.concurrent.locks.ReentrantLock; /** * @Author suaxi * @Date 2020/11/26 18:09 * 测试Lock锁 */ public class TestLock { public static void main(String[] args) { TestLock2 testLock2 = new TestLock2(); new Thread(testLock2).start(); new Thread(testLock2).start(); new Thread(testLock2).start(); } } class TestLock2 implements Runnable{ int ticketNums = 10; //定义锁 private final ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true){ lock.lock(); //加锁 try { if (ticketNums>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNums--); }else { break; } }finally { lock.unlock(); //解锁 } } } }synchronized与Lock对比1、Lock是显示锁(手动开启和关闭);synchronized是隐式锁,出了作用域自动释放2、Lock只有代码块锁,synchronized有代码块锁和方法锁3、使用Lock锁时,JVM将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供更多的子类)4、优先使用顺序:Lock --->同步代码块(已经进入了方法体,分配了相应资源) --->同步方法(在方法体之外)
2020年11月26日
58 阅读
0 评论
0 点赞
2020-11-26
线程通信
线程通信分析:这是一个线程同步问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件对于生产者,没有生产产品之前,要通知消费者等待,而生产了产品之后,又需要马上通知消费者消费对于消费者,在消费之后,要通知生产者已经消费结束,需要生产新的产品以供消费在生产者消费者问题中,仅有synchronized是不够的synchronized可阻止并发更新同一个共享资源,实现同步synchronized不能用来实现不同线程之间的消息传递(通信)应用场景:假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走消费如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止如果仓库中有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止解决方式一并发协作模型“生产者/消费者模式”(管程法)生产者:负责生产数据的模块消费者:负责处理数据的模块缓冲区:消费者不能直接使用生产者的数据,他们之间有个缓冲区生产者将生产好的产品放入缓冲区,消费者从缓冲区拿出数据package com.thread.threadDemo; /** * @Author suaxi * @Date 2020/11/26 20:58 * 生产者消费者模型,利用缓冲区解决(管程法) */ public class TestPC01 { public static void main(String[] args) { SynContainer container = new SynContainer(); new Productor(container).start(); new Comsumer(container).start(); } } //生产者 class Productor extends Thread{ SynContainer container; public Productor(SynContainer container){ this.container = container; } //生产 @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Chicken(i)); System.out.println("生产了"+i+"只鸡"); } } } //消费者 class Comsumer extends Thread{ SynContainer container; public Comsumer(SynContainer container){ this.container = container; } //消费 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费了"+container.pop().id+"只鸡"); } } } //产品 class Chicken{ int id; public Chicken(int id) { this.id = id; } } //缓冲区 class SynContainer{ //需要一个容器大小 Chicken[] chickens = new Chicken[10]; //容器计数器 int count = 0; //生产者放入产品 public synchronized void push(Chicken chicken){ //如果容器满了,就需要等待消费者消费 if(count==chickens.length){ //通知消费者消费,生产等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,就需要放入产品 chickens[count] = chicken; count++; //再通知消费者消费 this.notify(); } //消费者消费产品 public synchronized Chicken pop(){ //判断能否消费 if (count==0){ //等待生产者生产,消费者等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费 count--; Chicken chicken = chickens[count]; //吃完了,通知生产者生产 this.notify(); return chicken; } }解决方式二信号灯法package com.thread.threadDemo; /** * @Author suaxi * @Date 2020/11/26 21:40 * 测试生产者消费者问题2:信号灯法(标志位) */ public class TestPC02 { public static void main(String[] args) { TV tv = new TV(); new Player(tv).start(); new Watcher(tv).start(); } } //生产者(演员) class Player extends Thread{ TV tv; public Player(TV tv){ this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if(i%2==0){ this.tv.play("新闻联播"); }else { this.tv.play("洗碗机广告"); } } } } //消费者(观众) class Watcher extends Thread{ TV tv; public Watcher(TV tv){ this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { this.tv.watch(); } } } //产品(节目) class TV{ //演员表演,观众等待 true //观众观看,演员等待 false String voice; //节目 boolean flag = true; //表演 public synchronized void play(String voice){ if (!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("演员表演了:"+voice); //通知观众观看 this.notify(); //通知唤醒 this.voice = voice; this.flag = !this.flag; } //观看 public synchronized void watch(){ if (flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观看了:"+voice); //通知演员表演 this.notify(); this.flag = !this.flag; } }
2020年11月26日
64 阅读
0 评论
0 点赞
2020-11-26
死锁
死锁定义:多个线程互相拥抱着对方需要的资源,然后形成僵持产生死锁的四个必要条件:1、互斥:一个资源每次只能被一个进程使用2、请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放3、不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺4、循环等待:若干进程之间形成一种头尾相接的循环等待资源关系死锁实例:package com.thread.threadDemo; /** * @Author suaxi * @Date 2020/11/26 16:18 * 死锁:多个线程互相拥抱着对方需要的资源,然后形成僵持 */ public class DeadLock { public static void main(String[] args) { MakeUp p1 = new MakeUp(0, "孙笑川"); MakeUp p2 = new MakeUp(1, "药水哥"); p1.start(); p2.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } class MakeUp extends Thread{ //需要的资源只有一份,用statick来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice; //选择 String name; //使用人 public MakeUp(int choice,String name){ this.choice = choice; this.name = name; } @Override public void run() { //化妆 try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } private void makeup() throws InterruptedException { if (choice==0){ synchronized (lipstick){ //拿到口红 System.out.println(this.name+"获得口红的锁"); Thread.sleep(1000); synchronized (mirror){ //等待一秒后想拿镜子 System.out.println(this.name+"获得镜子的锁"); } } }else { synchronized (mirror){//拿到镜子 System.out.println(this.name+"获得镜子的锁"); Thread.sleep(2000); synchronized (lipstick) { //等待两秒后想拿口红 System.out.println(this.name + "获得口红的锁"); } } } } }将choice==0中的synchronized (mirror)拿到synchronized (lipStick)之外,else中的代码同理,即可解决实例中的死锁问题package com.thread.threadDemo; /** * @Author suaxi * @Date 2020/11/26 16:18 * 死锁:多个线程互相拥抱着对方需要的资源,然后形成僵持 */ public class DeadLock { public static void main(String[] args) { MakeUp p1 = new MakeUp(0, "孙笑川"); MakeUp p2 = new MakeUp(1, "药水哥"); p1.start(); p2.start(); } } //口红 class Lipstick{ } //镜子 class Mirror{ } class MakeUp extends Thread{ //需要的资源只有一份,用statick来保证只有一份 static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); int choice; //选择 String name; //使用人 public MakeUp(int choice,String name){ this.choice = choice; this.name = name; } @Override public void run() { //化妆 try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } private void makeup() throws InterruptedException { if (choice==0){ synchronized (lipstick){ //拿到口红 System.out.println(this.name+"获得口红的锁"); Thread.sleep(1000); } synchronized (mirror){ //等待一秒后想拿镜子 System.out.println(this.name+"获得镜子的锁"); } }else { synchronized (mirror){//拿到镜子 System.out.println(this.name+"获得镜子的锁"); Thread.sleep(2000); } synchronized (lipstick) { //等待两秒后想拿口红 System.out.println(this.name + "获得口红的锁"); } } } }
2020年11月26日
56 阅读
0 评论
0 点赞
2020-11-26
线程同步
线程同步由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制 synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用释放锁即可,但同时也会带来如下问题:一个线程持有锁会导致其他所有需要此锁的线程挂起在多线程竞争下,加锁、释放锁会导致频繁的 上下文切换 和 调度延时,引起性能问题如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题同步方法synchronized关键字包括synchronized方法和synchronized块两种方法同步方法 public synchronized void method(int args){}synchronized方法控制对象的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行同步块同步块 synchronized(Obj){}(Obj){}同步监视器Obj可以是任何对象,推荐使用共享资源作为同步监视器同步方法中无须指定同步监视器,因为同步方法的同步监视器就是这个对象本身,或者是class执行过程第一个线程访问,锁定同步监视器,执行其中代码第二个线程访问,发现同步监视器被锁定,无法访问第一个线程访问完毕,释放同步监视器锁第二个线程访问,发现同步监视器没有锁,锁定并进行访问买票问题package com.thread.syn; /** * @Author suaxi * @Date 2020/11/26 14:40 * 不安全的买票,结果中出现负的票数 */ public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket buyTicket = new BuyTicket(); new Thread(buyTicket,"孙笑川").start(); new Thread(buyTicket,"药水哥").start(); new Thread(buyTicket,"Giao哥").start(); } } class BuyTicket implements Runnable{ //票 private int ticketNums = 10; //外部停止标志 boolean flag = true; @Override public void run() { while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } //synchronized同步方法 private synchronized void buy() throws InterruptedException { //判断是否有票 if (ticketNums<=0){ flag = false; return; } //模拟延时 Thread.sleep(100); //买票 System.out.println(Thread.currentThread().getName()+"买到了票"+ticketNums--); } }模拟取款package com.thread.syn; /** * @Author suaxi * @Date 2020/11/26 15:03 */ public class UnsafeBank { public static void main(String[] args) { //账户 Account account = new Account(100, "存折"); Drawing sun = new Drawing(account, 50, "孙笑川"); Drawing yao = new Drawing(account, 100, "药水哥"); sun.start(); yao.start(); } } //账户 class Account{ int money; //余额 String name; //账户名 public Account(int money, String name) { this.money = money; this.name = name; } } //银行:模拟取款 class Drawing extends Thread{ Account account; //账户 int drawingMoney; //取款额度 int cash; //现金 public Drawing(Account account,int drawingMoney,String name){ super(name); this.account = account; this.drawingMoney = drawingMoney; } //取钱 //synchronized 默认锁的是this. @Override public void run() { //synchronized锁的对象就是变化的量,即需要增删改的对象 synchronized (account){ //判断余额 if (account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"账户余额不足"); return; } //sleep可以放大问题的发生性 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //余额 = 卡内余额 - 取款额度 account.money = account.money - drawingMoney; //现金 cash = cash + drawingMoney; System.out.println(account.name+"账户余额:"+account.money); //继承Thread类,所以此处的this.getName() = Thread.currentThread().getName() System.out.println(this.getName()+"现金:"+cash); } } }线程不安全的集合package com.thread.syn; import java.util.ArrayList; import java.util.List; /** * @Author suaxi * @Date 2020/11/26 14:59 * 线程不安全的集合 */ public class UnsafeList { public static void main(String[] args) { List<String> list = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(() ->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } } 补充:JUC安全类型的集合CopyOnWriteArrayListpackage com.thread.syn; import java.util.concurrent.CopyOnWriteArrayList; /** * @Author suaxi * @Date 2020/11/26 15:48 * 测试JUC安全类型的集合 */ public class TestJUC { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>(); for (int i = 0; i < 1000; i++) { new Thread(() ->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
2020年11月26日
56 阅读
0 评论
0 点赞
1
...
16
17
18
...
20