- 博客(65)
- 收藏
- 关注
原创 SpringMVC基本结构
服务端三层架构分为:表现层、业务层、数据层(持久层)。表现层调用业务层,业务层调用数据层。MVC模式分为三层:控制层(负责处理请求)、模型层(控制层与视图层的纽带)、视图层(负责渲染),这三层集体解决表现层的问题。客户端请求访问服务器,访问的是Controller控制器,这个控制器组件接收请求中的数据,然后去调用业务层处理,处理完成后会将得到的数据封装到model中,并传给视图层,视图层利用数据生成html,返回给浏览器,最终浏览器通过视图层得到了html。...
2022-05-16 22:40:05
618
原创 原子引用解决ABA问题(对应思想:乐观锁)
线程a是捣乱线程,将2改为3,又将3改回了2。这里使用带时间戳的原子引用(给数据增加版本号标识),每次修改了数据之后,会对数据的版本号进行加一操作。线程a通过两次修改,最终结果仍然是2,但是它中间是动了数据,由于每次修改数据完毕都会将数据的版本号加一,那么在b线程准备提交修改的数据时(将2改为3),虽然比对的数据是2,但是这个2不是原来的2,数据的版本号已经不是最初它拿到的版本号(这两个2的版本号不一样),说明这个数据中间被动了,所以b线程的修改不成功,会返回false。package com.han
2022-05-13 22:15:14
173
原创 DCL懒汉式(volatile关键字禁止指令重排的应用)
package com.han.demo01;public class TestLazyMan { public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(() -> { LazyMan.getInstance(); }).start(); } }}c
2022-05-13 17:23:32
336
原创 线程池三大方法、七大参数、四种拒绝策略
优化资源的使用 -->池化技术线程池、连接池、内存池、对象池。。。(创建和销毁十分浪费资源)池化技术:事先贮备好一些资源,要用,就来这里拿,用完之后还回来线程池的好处:降低资源的消耗提高的响应速度方便管理线程复用,可以控制最大并发数、管理线程一、三大方法1、newSingleThreadExecutor() 单个线程package com.han.demo01;import java.util.concurrent.ExecutorService;import java.uti
2022-05-11 17:10:50
336
2
原创 读写锁(共享锁、独占锁)
package com.han.demo01;import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * 独占锁(写锁):一次只能被一个线程占有 * 共享锁(读锁):多个线程可以同时占有 * ReadWriteLock * 读-读 可以共
2022-05-10 22:28:59
266
原创 Semaphore信号量使用(限流)
package com.han.demo01;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;public class TestXHL { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3);//单个参数为资源数量 for (int i = 1; i &
2022-05-10 21:53:24
176
原创 CyclicBarrier的使用
package com.han.demo01;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;public class CB { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {//一旦
2022-05-10 21:38:33
92
原创 CountDownLatch使用
主要方法:countDown()、await()downLatch.countDown(); //数量-1downLatch.await();//等待计数器归零,然后再往下执行每次线程调用countDown()数量-1,假设计数器变成0,downLatch.await()就会被唤醒,继续执行!如果没有使用await方法,那么主线程其实是一直在跑的,所以还没等上面的六个线程跑完,主线程关门就已经输出了。package com.han.demo01;import java.util.concurre
2022-05-10 21:23:11
7076
原创 Condition实现精准通知唤醒
package com.han.demo01;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class TestCondition { public static void main(String[] args) { Data02 data = n
2022-05-08 15:29:56
359
原创 lock的使用
1、获取lock锁对象2、通过lock锁对象创建Condition实例绑定到lock锁对象上3、上锁:lock.lock()4、try…catch执行业务5、finally中释放锁:lock.unlock()package com.han.demo01;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.Re
2022-05-04 22:51:45
1490
原创 生产者和消费者问题 Synchronized 版本,防止虚假唤醒
package com.han.demo01;public class TestPC { public static void main(String[] args) { Data data = new Data(); new Thread(() -> { for (int i = 0; i < 20; i++) { try { data.increment
2022-05-03 22:44:57
335
原创 lock与synchronized基本使用对比
synchronized(作为关键字):package com.han.demo01;public class TestSaleTicket { public static void main(String[] args) { Ticket t = new Ticket(); new Thread(() -> { for (int i = 0; i < 60; i++) { t.sale();
2022-04-28 22:30:21
315
原创 多线程售票解耦写法(使用传统synchronized 关键字)
解耦前:类SaleTicket与Runnable永远捆绑在了一起,它会变成一个线程类,而不是一个纯粹的类,不能很好体现OOP思想。package com.han.demo01;public class TestComparedSaleTicket { public static void main(String[] args) { SaleTicket st = new SaleTicket(); new Thread(st, "窗口1").start();
2022-04-26 21:36:05
294
原创 lambda表达式
本例子中 ,从普通类->静态内部类->局部内部类->匿名内部类->lambda表达式,整体的代码繁杂程度由繁至简。函数式接口:任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。对于函数式接口,我们可以通过lambda表达式来创建该接口的对象lambda表达式只有一行代码的情况下才可以简化成一行,如果有多行,那么就用代码块包裹前提是接口为函数式接口多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号(单个参数可以省略括号)package creatth
2022-04-22 22:16:03
175
原创 模板方法设计模式
https://carsonho.blog.youkuaiyun.com/article/details/54910518https://blog.youkuaiyun.com/bighuan/article/details/62940515
2022-04-22 20:07:10
139
原创 线程的底部实现原理—静态代理模式
静态代理:真实方法和代理方法的名字和参数等相同,方法体不同即可,代理类与被代理类通过实现一个相同的接口来建立起联系代理对象(WeddingCompany 的对象)要代理真实对象(You 的对象)静态代理优点:代理对象可以做很多真实对象做不了的事情真实对象专注做自己的事情package creatthread;public class StaticProxy { public static void main(String[] args) { System.o
2022-04-22 20:00:34
265
原创 创建线程的三种方式
利用url下载网图的类:package creatthread;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;//需要commons-io-2.6 jar包public class WebPicDownLoad { public void download(String url, String pathName) {
2022-04-22 17:20:49
204
原创 类的加载与ClassLoader的理解
1、加载:将类的class字节码文件加载到内存中,并把静态数据转换成方法区(特殊的堆)的运行时数据结构。在此阶段,生成代表这个类的java.lang.Class对象。2、链接:将Java类的二进制数据合并到JRE中验证:确保加载的类类信息符合JVM规范,没有安全方面的问题;准备:正式为类变量(static)分配内存,并设置类变量默认初始值,这些内存都是在方法区中进行分配;解析:将JVM常量池中的符号引用(常量名)替换为直接引用(地址)。3、初始化:执行由类的static(静态代码块、静..
2022-04-20 20:52:59
869
原创 C3P0数据库连接池使用
配置文件:(注意:c3p0的xml配置文件名必须为 c3p0-config ,否则会报空指针)<?xml version="1.0" encoding="UTF-8"?><c3p0-config> <!-- c3p0的缺省(默认)配置 如果在代码中ComboPooledDataSource ds=new ComboPooledDataSource();这样写就表示使用的是c3p0的缺省(默认) --> <defaul
2022-04-19 19:08:26
564
原创 DBCP使用
配置文件:#连接设置driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=trueusername=rootpassword=123456#初始化连接initialSize=10#最大连接数量maxActive=50#最大空闲连接maxIdle=20#最小空闲连接m
2022-04-19 18:04:58
808
原创 JDBC操作事务
package com.hyc.study04;import com.hyc.study02.utils.JDBCUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class TestTransaction { public static void main(String[] ar
2022-04-19 16:12:17
74
原创 PreparedStatement防止SQL注入
添加数据:package com.hyc.study03;import com.hyc.study02.utils.JDBCUtils;import java.sql.Connection;import java.sql.ResultSet;import java.util.Date;import java.sql.PreparedStatement;import java.sql.SQLException;public class TestInsert { public stat
2022-04-19 15:48:53
1611
原创 SQL注入
1、正常登陆:package com.hyc.study02;import com.hyc.study02.utils.JDBCUtils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class PourIntoSql { public static void main(String[] args)
2022-04-18 22:46:07
445
原创 JDBC工具类封装
jdbc工具类的封装:package com.hyc.study02.utils;import java.io.InputStream;import java.sql.*;import java.util.Properties;public class JDBCUtils { private static String driver = null; private static String url = null; private static String userna
2022-04-18 22:14:44
1216
2
原创 JDBC连接数据库
主要步骤:1、加载数据库驱动2、获取数据库连接(包含了获取用户信息、url)3、创建执行sql的对象4、执行sql语句5、返回执行的结果集6、释放连接package com.hyc.study01;import java.sql.*;public class JdbcFirstDemo { public static void main(String[] args) throws ClassNotFoundException, SQLException { //
2022-04-16 16:29:03
370
原创 创建二叉树
package binaryTree;import java.util.*;//定义二叉树的结点class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(){ } public TreeNode(int val){ this.val = val; } public TreeNode(int val, TreeNode left,
2022-03-28 10:18:51
1397
原创 事实最终变量与最终变量
事实最终变量是指一旦被赋值以后就不会被改变的量,不意味着必须被final修饰才行。比如在某个方法中有int a = 23; 而这个变量a在这被初始化赋值后,它的值再也没有被改变过(虽然它本身可以被改变),那么这个a就可以称为事实最终变量。最终变量:使用关键字final声明变量称为最终变量。最终变量只能进行一次赋值(也就是说一旦初始化之后就不能再改变变量的值了)...
2022-03-19 17:29:54
545
1
原创 自定义异常类
①继承于现有的异常结构:RuntimeException Exception②提供全局常量 serialVersionUID 序列号(类的唯一标识)③提供重载的构造器eg:package exceptiontest;public class EcDef extends Exception { static final long serialVersionUID = -7034897190766939L; public EcDef() { } ; publ
2021-06-17 19:58:50
88
原创 异常的处理:抓抛模型
过程一:“抛”:程序在正常执行过程当中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出。一旦抛出对象以后,其后的代码就不再执行了。关于异常对象的产生:①系统自动生成异常对象 ;②手动生成一个异常对象,并抛出(throw)过程二:“抓”:可以理解为异常的处理方式:(1)try-catch-finally(2)throwsthrow:异常对象产生的一种方式,手动产生一个异常对象;(位于方法体内)throws:处理异常的一种方式;(位于方法声明处)...
2021-06-16 21:17:43
215
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人