Java,JDBC核心技术,线程池,事务
文章目录
- JDBC核心技术
- 一、概述
- 1. 数据的持久化
- 2. Java中的数据存储技术
- 3. JDBC介绍
- 4. JDBC体系结构
- 5. JDBC程序编写步骤
- 二、获取数据库连接
- 三、PrepareStatement
- 1. 操作和访问数据库
- 2. 使用Statement操作数据表的弊端
- 3. PreparedStatement VS Statement
- 4. 使用PreparedStatement操作数据表
- 4.1 添加数据
- 4.2 批量操作
- 四、操作BLOB类型字段
- 1. BLOB类型
- 2. 对BLOB类型数据的操作
- 2.1 插入操作
- 2.2 查询操作
- 五、数据库事务
- 1. 数据库事务介绍
- 2. 数据提交
- 3. 事务的ACID属性
- 4. 事务的隔离级别
- 六、数据库连接池
- 1. 问题引入
- 2. 概述
- 3. 多种开源数据库连接池
- 3.1 C3P0
- 3.2 Druid
- 七、Apache-DBUtils
- 1. 简介
- 2. 测试
- 八、参考资料
JDBC核心技术
一、概述
1. 数据的持久化
- 持久化:把数据保存到可掉电式存储设备中以供之后使用。数据持久化意味着将内存中的数据保存到硬盘上加以“固化”,而持久化的实现过程大多通过各种关系数据库来完成。
- 持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。
2. Java中的数据存储技术
- 在Java中,数据存取技术可分为如下几类:
- JDBC直接访问数据库
- JDO(Java Data Object)技术
- 第三方O/R工具,如Hibernate,Mybatis等
- JDBC是Java访问数据库的基石,JDO、Hibernate、MyBatis等只是更好的封装了JDBC
3. JDBC介绍
- JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取数据和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(Java.sql,Javax.sql)使用这些类库可以以一种标准的方法、方便的访问数据库资源。
- JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题
- JDBC的目标是使Java程序员使用JDBC可以连接任何提供JDBC驱动程序的数据库系统
- 若没有JDBC则Java程序访问数据库时是这样的:
- JDBC,Java访问数据库时:
4. JDBC体系结构
- JDBC接口(API)包括两个层次:
- 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库、执行SQL语句、获得结果)
- 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序使用
5. JDBC程序编写步骤
二、获取数据库连接
public class ConnectionTest {/*** 方式一* @throws SQLException*/@Testpublic void testConnection1() throws SQLException {//1、获取Driver的实现类对象Driver driver=new com.mysql.jdbc.Driver();//2、提供要连接的数据库:stu为其中的一个数据库名String url="jdbc:mysql://localhost:3306/stu";//3、封装用户名和密码Properties info=new Properties();info.setProperty("user","root");info.setProperty("password","123456");Connection conn = driver.connect(url, info);System.out.println(conn);}/*** 方式二:对方式一的迭代:在如下的程序中不出现第三方的API,使程序具有更好的可移植性*/@Testpublic void testConnection2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {//1、获取Driver实现类对象Class aClass = Class.forName("com.mysql.jdbc.Driver");Driver driver= (Driver) aClass.newInstance();//2、提供需要连接的数据库String url="jdbc:mysql://localhost:3306/stu";Properties info=new Properties();info.setProperty("user","root");info.setProperty("password","123456");//4、获取连接Connection conn = driver.connect(url, info);System.out.println(conn);}/*** 方式三:迭代方式二:使用DriverManger替换Driver* @throws Exception*/@Testpublic void testConnection3() throws Exception {//1、获取Driver实现类对象Class aClass = Class.forName("com.mysql.jdbc.Driver");Driver driver= (Driver) aClass.newInstance();//2、获取基本信息String url="jdbc:mysql://localhost:3306/stu";String user="root";String password="123456";//3、注册驱动DriverManager.registerDriver(driver);//4、获取连接Connection conn = DriverManager.getConnection(url, user, password);System.out.println(conn);}/*** 方式四:只加载驱动,不用显式注册驱动* @throws Exception*/@Testpublic void testConnection4() throws Exception {//1、获取基本信息String url="jdbc:mysql://localhost:3306/stu";String user="root";String password="123456";//2、加载DriverClass.forName("com.mysql.jdbc.Driver");//3、获取连接Connection conn = DriverManager.getConnection(url, user, password);System.out.println(conn);}/*** 最终版*/@Testpublic void testConnection5() throws ClassNotFoundException, SQLException, IOException {//1、读取配置文件中的基本信息FileInputStream fs = new FileInputStream("jdbc.properties");Properties ps = new Properties();ps.load(fs);String user = ps.getProperty("user");String password = ps.getProperty("password");String url = ps.getProperty("url");String driver = ps.getProperty("driver");//2、加载驱动Class.forName(driver);//3、获取连接Connection conn = DriverManager.getConnection(url, user, password);System.out.println(conn);}
}
三、PrepareStatement
1. 操作和访问数据库
- 数据库连接被用于向数据库服务器发送命令和SQL语句,并接受数据库服务器返回的结果。
- 在Java.sql包中有三个接口分别定义了对数据库的调用的不同方式:
- Statement:用于执行静态SQL语句并返回它所生成结果的对象
- PrepatedStatement:SQL语句被预编译并存储在此对象中,可以使用此对象多次高效的执行该语句
- CallableStatement:用于执行SQL存储过程
2. 使用Statement操作数据表的弊端
通过调用Connection对象的createStatement()方法创建对象。该对象执行静态的SQL语句,并且返回执行结果
Statement接口中定义了下列方法用于执行SQL语句
int excuteUpdate(String sql);//执行更新操作INSERT、UPDATE、DELETE ResultSet executeQuery(String sql);//执行查询操作SELECT
使用Statement操作数据表存在弊端:
- 问题一:存在拼串操作,繁琐
- 问题二:存在SQL注入问题
SQL注入是利用某些系统没有对用户输入的数据进行充分的检验,而在用户输入数据中注入非法的SQL语句段或命令(如:SELECT user, password FROM user_table WHERE user='a’OR1='ADN password=‘OR’1’=‘1’),从而利用系统对SQL引擎完成恶意行为的做法
对于Java而言,要防范SQL注入,则使用PreparedStatement取代Statement
3. PreparedStatement VS Statement
- 代码的可读性和可维护性
- PreparedStatement能最大可能提高性能:
- DBServe会对预编译语句提供性能优化。因为预编译语句有可能被重复使用,语句在被DBServer的编译器编译后的执行代码缓存下来,下次在调用时只要是相同的编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会被执行
- 在Statement语句中,即使是相同的操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义,没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
- PreparedStatement可以防止SQL注入
4. 使用PreparedStatement操作数据表
4.1 添加数据
public class PreparedStatementUpdateTest {@Testpublic void test() {Connection conn = null;PreparedStatement pps = null;try {FileInputStream fs = new FileInputStream("jdbc.properties");Properties ps = new Properties();ps.load(fs);String user=ps.getProperty("user");String password=ps.getProperty("password");String url=ps.getProperty("url");String driver=ps.getProperty("driver");//2、加载驱动Class.forName(driver);//3、获取连接conn = DriverManager.getConnection(url, user, password);//4、预编译SQL语句,返回PreparedStatement实例String sql="insert into book(name,author,price,type)values(?,?,?,?)";pps = conn.prepareStatement(sql);//5、填充占位pps.setString(1,"三国演义");pps.setString(2,"罗贯中");pps.setString(3,"30");pps.setString(4,"小说");//6、执行操作pps.execute();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {//7、关闭资源try {if(pps!=null){pps.close();}} catch (SQLException e) {e.printStackTrace();}try {if(conn!=null){conn.close();}} catch (SQLException e) {e.printStackTrace();}}}
}
4.2 批量操作
- update、delete本身就具有批量操作的效果
- 此处批量操作主要指批量插入
public class InsertTest {@Testpublic void test(){Connection conn = null;PreparedStatement ps = null;try {conn = JDBCUtils.getConnection();//方式三:设置不允许自动提交数据conn.setAutoCommit(false);String sql="insert into goods(name)values(?)";ps = conn.prepareStatement(sql);final int value=1000000;long start = System.currentTimeMillis();for (int i = 0; i <value ; i++) {ps.setObject(1,"name_"+i);//方式一
// ps.execute();//方式二//1、“攒”SQLps.addBatch();if(i%500==0){//2、执行batchps.executeBatch();//3、清空batchps.clearBatch();}}//统一提交数据conn.commit();long end = System.currentTimeMillis();System.out.println("执行时间为:"+(end-start));//方式一执行时间为:29135//方式二执行时间为:279 1000000--->执行时间为:9568//方式三:1000000--->执行时间为:5000} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn,ps);}}
}
- 注意:MYSQL服务器默认是关闭批处理操作,需要通过在配置文件url后添加参数开启批处理。
四、操作BLOB类型字段
1. BLOB类型
- MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据
- 插入BLOB类型的数据类型必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接
- MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)
类型 | 大小(单位:字节) |
---|---|
TinyBlob | 最大 255 |
Blob | 最大 65K |
MediumBlob | 最大 16M |
LongBlob | 最大4 G |
- 实际使用中根据需要存入的数据大小定义不同的BLOB类型
- 如果存储文件过大数据库性能会下降
2. 对BLOB类型数据的操作
2.1 插入操作
public class BlobTest {/*** 向数据表customer中插入Blob类型的字段* @throws Exception*/@Testpublic void testInsert() throws Exception {Connection conn = JDBCUtils.getConnection();String sql="insert into customers(name,image)values(?,?)";PreparedStatement ps = conn.prepareStatement(sql);ps.setObject(1,"房东的猫");FileInputStream fs = new FileInputStream(new File("房东的猫1.jpg"));ps.setObject(2,fs);ps.execute();JDBCUtils.closeResource(conn,ps);}
}
2.2 查询操作
public class BlobTest { @Testpublic void testQuery() {Connection conn = null;PreparedStatement ps = null;FileOutputStream fos =null;InputStream bs =null;ResultSet rs =null;try {conn = JDBCUtils.getConnection();String sql="select id,name,image from customers where id=?";ps = conn.prepareStatement(sql);ps.setInt(1,2);rs = ps.executeQuery();if(rs.next()){//1、方式一/*int id=rs.getInt(1);String name = rs.getString(2);*///2、方式二int id = rs.getInt("id");String name = rs.getString("name");Customer cust = new Customer(id, name);System.out.println(cust.toString());//将Blob类型字段下载下来,以文件形式保存在本地Blob image = rs.getBlob("image");bs = image.getBinaryStream();fos = new FileOutputStream(new File("zjl2.jpg"));byte[] buffer = new byte[1024];int len;while((len=bs.read(buffer))!=-1){fos.write(buffer,0,len);}}} catch (Exception e) {e.printStackTrace();} finally {try {if(rs!=null){rs.close();}} catch (SQLException e) {e.printStackTrace();}try {if(fos!=null){fos.close();}} catch (IOException e) {e.printStackTrace();}try {if(bs!=null){bs.close();}} catch (IOException e) {e.printStackTrace();}JDBCUtils.closeResource(conn,ps);}}
}
五、数据库事务
1. 数据库事务介绍
- 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态
- 事务处理(事务操作):保证所有事务都作为一个工作单元执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,那么所有的事务都被提交(Commit),那么这些修改就永久的保存下来;要么数据库管理系统将放弃所做的所有修改,整个事务回滚(rollback)到最初状态
- 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元,当他全部完成时,数据的一致性可以保持,而当这个单元的一部分操作失败,整个事务应全部视为错误,所以从起始点以后的操作应全部回退到开始状态。
2. 数据提交
- 数据一旦提交就不可回滚
- DDL操作一旦执行,都会自动提交
- DML默认情况下,一旦执行,就会自动提交
- 通过set autocommit=false的方式取消DML操作的自动提交
- 默认在关闭连接时会自动提交数据
/*** @Description TODO* @Author YunShuaiWei* @Date 2020/6/22 11:44* @Version**/
public class TransactionUpdate {@Testpublic void testUpdate() {Connection conn = null;PreparedStatement ps1 = null;PreparedStatement ps2 = null;try {conn = JDBCUtils.getConnection();//关闭自动提交conn.setAutoCommit(false);String sql1 = "update account set money=money-100 where id=?";String sql2 = "update account set money=money+100 where id=?";ps1 = conn.prepareStatement(sql1);ps1.setInt(1, 2);ps1.execute();//模拟异常int i = 1 / 0;ps2 = conn.prepareStatement(sql2);ps2.setInt(1, 3);ps2.execute();//数据的提交conn.commit();} catch (Exception e) {e.printStackTrace();try {if (conn != null) {//事务回滚conn.rollback();}} catch (SQLException throwables) {throwables.printStackTrace();}} finally {try {if (ps1 != null) {ps1.close();}if (ps2 != null) {ps2.close();}if (conn != null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}}
}
3. 事务的ACID属性
- 原子性(Atomicity)
- 事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
- 一致性(Consistency)
- 必须使数据库从一个一致性状态变化为另一个一致性状态
- 隔离性(Isolation)
- 一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并执行的各个事务之不能相互干扰
- 持久性(Durability)
- 一个事务一旦提交,它对数据库中数据的改变是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
4. 事务的隔离级别
隔离级别 | 描述 |
---|---|
READ UNCOMMITED(读未提交数据) | 允许事务读取未被其他事务提交的变更,脏读、不可重复读和幻读的问题都会出现 |
READ COMMITED (读已提交数据) | 只允许事务读取已经被其他事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然可能出现 |
REPEABLE READ (不可重复读) | 确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读,但幻读的问题仍然存在 |
(SERIALIZABLE (串行化)) | 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入,更新和删除操作,所有并发问题都可以避免,但性能十分低 |
六、数据库连接池
1. 问题引入
- 在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤:
- 在主程序中建立连接
- 进行sql操作
- 断开数据库连接
- 存在的问题
- 普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接时都要将Connection加载到内存,再验证用户名和密码。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式会消耗许多资源和时间,数据库连接资源并没有得到很好的重复利用
- 对于每一个数据库连接,使用完后都得断开,否则如果程序出现异常而未能关闭,将会导致数据库系统中内存泄漏,最终将导致重启数据库
- 这种开发不能控制被创建的连接对象数,系统资源会被毫无顾忌的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃
2. 概述
- 为解决传统开发中的数据库连接问题,可以采用数据库连接池技术
- 数据库连接池的基本思想:为数据库连接建立一个"缓冲池"。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取出一个,使用完毕后再放回
- 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
- 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定在这个连接池能占有的最大连接数,当应用程序向连接池请求数超过最大连接数量时,这些请求将被加入等待队列中
3. 多种开源数据库连接池
- JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由服务器(Weblogic、WebSphere、Tomcat)提供实现,也有一些开源组织提供实现:
- DBCP是Apache提供的数据库连接池。Tomcat服务器自带的dbcp数据库连接池,速度相对c3p0较快
- C3P0是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性较好
- Proxool是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能
- BoneCP是一个开源组织提供的数据库连接池,速度快
- Druid是阿里提供的数据库连接池,集DCCP、C3P0、Proxool优点于一身
- DataSource通常被称为数据源,它包含连接池和连接池管理两部分,习惯上经常把DataSource称为连接池
- DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度
3.1 C3P0
- 测试连接
/*** @Description TODO* @Author YunShuaiWei* @Date 2020/6/22 21:21* @Version**/
public class DataSourceTest {@Testpublic void testGetConnection() throws Exception {//获取c3p0数据库连接池ComboPooledDataSource cpds = new ComboPooledDataSource();cpds.setDriverClass("com.mysql.jdbc.Driver");cpds.setJdbcUrl("jdbc:mysql://localhost:3306/ysw");cpds.setUser("root");cpds.setPassword("****");//初始数据库连接数cpds.setInitialPoolSize(10);//获取连接Connection conn = cpds.getConnection();System.out.println(conn);}//使用配置文件@Testpublic void testGetConnection1() throws Exception {ComboPooledDataSource cpds = new ComboPooledDataSource("hello");Connection conn = cpds.getConnection();System.out.println(conn);}
}
- 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><!-- This app is massive! --><named-config name="hello"><property name="user">root</property><property name="password">****</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/ysw</property><property name="driverClass">com.mysql.jdbc.Driver</property><!--当数据库连接池中的连接数不够时,c3p0一次性向数据库服务器申请的连接数--><property name="acquireIncrement">5</property><!--数据库连接池中初始化时的连接数--><property name="initialPoolSize">10</property><!--维护最小的连接--><property name="minPoolSize">50</property><!--维护最大的连接数--><property name="maxPoolSize">1000</property><!--数据库连接池最多维护的Statement的个数--><property name="maxStatements">50</property><!--每个连接中最多可以使用的Statement的个数--><property name="maxStatementsPerConnection">5</property></named-config>
</c3p0-config>
3.2 Druid
- 测试连接
@Testpublic void druidTest() throws Exception {Properties p = new Properties();FileInputStream fs = new FileInputStream(new File("druid.properties"));p.load(fs);DataSource ds = DruidDataSourceFactory.createDataSource(p);Connection conn = ds.getConnection();System.out.println(conn);}
- druid.properties文件
url=jdbc:mysql://localhost:3306/ysw
username=root
password=****
driverClassName=com.mysql.jdbc.Driver
七、Apache-DBUtils
1. 简介
- Commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本低
- 封装了针对数据库的增删改查操作
2. 测试
- JDBCUtils工具类
public class JDBCUtils {//关闭资源public static void closeResource(Connection conn, PreparedStatement pps){try {if(pps!=null){pps.close();}} catch (SQLException e) {e.printStackTrace();}try {if(conn!=null){conn.close();}} catch (SQLException e) {e.printStackTrace();}}/*** 通过druid连接池获取连接* @Param []* @return java.sql.Connection**/public static Connection getDruidConnection(){Properties ps = new Properties();Connection conn = null;try {FileInputStream fs = new FileInputStream(new File("druid.properties"));ps.load(fs);DataSource ds = DruidDataSourceFactory.createDataSource(ps);conn = ds.getConnection();} catch (Exception e) {e.printStackTrace();}return conn;}
}
- CRUD
/*** @Description TODO* @Author YunShuaiWei* @Date 2020/6/23 10:19* @Version**/
public class dbUtilsTest {//插入测试@Testpublic void insertTest() {Connection conn = null;int i = 0;try {QueryRunner runner = new QueryRunner();conn = JDBCUtils.getDruidConnection();String sql = "insert into account(name,money)values(?,?)";i = runner.update(conn, sql, "yunsw", "1000");System.out.println("成功添加了 " + i + " 条记录!");} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, null);}}//查询测试@Testpublic void testQuery() {QueryRunner runn = new QueryRunner();Connection conn = JDBCUtils.getDruidConnection();String sql = "select * from account where id=?";BeanHandler<AccountDAO> handler = new BeanHandler<>(AccountDAO.class);AccountDAO query = null;try {query = runn.query(conn, sql, handler, 7);System.out.println(query);} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, null);}}//查询多条记录:BeanListHandler@Testpublic void testQueryBeanListHandler() {QueryRunner runner = new QueryRunner();Connection conn = JDBCUtils.getDruidConnection();String sql = "select id,name,money from account where money<?";BeanListHandler handler = new BeanListHandler(AccountDAO.class);try {List<AccountDAO> list = (List<AccountDAO>) runner.query(conn, sql, handler, 10000);list.forEach(System.out::println);} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, null);}}//查询特殊值@Testpublic void countTestScalarHandler() {Connection conn = null;try {QueryRunner runner = new QueryRunner();conn = JDBCUtils.getDruidConnection();String sql = "select Max(money) from account";ScalarHandler handler = new ScalarHandler();Double query = (Double) runner.query(conn, sql, handler);System.out.println(query);} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, null);}}
}
八、参考资料
- 尚硅谷JDBC核心技术(新版jdbc)
- 其他可关注个人博客!不将就
Java,JDBC核心技术,线程池,事务相关推荐
- Java常用四大线程池用法以及ThreadPoolExecutor详解
2019独角兽企业重金招聘Python工程师标准>>> 为什么用线程池? 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处-理效率 2.线程并发数量过多 ...
- Java并发编程——线程池的使用
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...
- 四十七、面试前,必须搞懂Java中的线程池ThreadPoolExecutor(上篇)
@Author:Runsen @Date:2020/6/9 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...
- java异常_Java线程池「异常处理」正确姿势:有病就得治
假设我们有一个线程池,由于程序需要,我们向该线程池中提交了好多好多任务,但是 这些任务都没有对异常进行try catch处理,并且运行的时候都抛出了异常 .这会对线程池的运行带来什么影响? 正确答案是 ...
- 自定义线程池-java内置线程池构造方法介绍
Java内置线程池原理剖析 我们要想自定义线程池,必须先了解线程池的工作原理,才能自己定义线程池:这里我们通过观察java中ThreadPoolExecutor的源码来学习线程池的原理; Thread ...
- Java多线程之线程池配置合理线程数
Java多线程之线程池配置合理线程数 目录 代码查看公司服务器或阿里云是几核的 合理线程数配置之CPU密集型 合理线程数配置之IO密集型 1. 代码查看公司服务器或阿里云是几核的 要合理配置线程数首先 ...
- Java多线程之线程池的手写改造和拒绝策略
Java多线程之线程池的手写改造和拒绝策略 目录 自定义线程池的使用 四种拒绝策略代码体现 1. 自定义线程池的使用 自定义线程池(拒绝策略默认AbortPolicy) public class My ...
- Java多线程之线程池7大参数、底层工作原理、拒绝策略详解
Java多线程之线程池7大参数详解 目录 企业面试题 线程池7大参数源码 线程池7大参数详解 底层工作原理详解 线程池的4种拒绝策略理论简介 面试的坑:线程池实际中使用哪一个? 1. 企业面试题 蚂蚁 ...
- Java多线程之线程池详解
Java多线程之线程池详解 目录: 线程池使用及优势 线程池3个常用方式 线程池7大参数深入介绍 线程池底层工作原理 1. 线程池使用及优势 线程池做的工作主要是控制运行的线程的数量,处理过程中将任务 ...
- java workerdone_【架构】Java并发编程——线程池的使用
前言 如果我们要使用线程的时候就去创建一个,这样虽然非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为 ...
最新文章
- 原创 | 电视广告流量预测中的“常识”陷阱,你掉进去了吗?
- 年轻人裸辞,需不需要“冷静期”?
- AI 学习之路——轻松初探 Python 篇(一)
- 2021-07-24
- Python编程专属骚技巧6
- python学习笔记7-模块、包
- c语言中转义字符efg,c语言的转义字符与空白符
- SAI红绿蓝三原色叠加效果
- 软件推荐:Picasa
- linux打包解压包(tar.gz )
- Initialization of variable was never used; consider replacing with assignment to ‘_’ or removing it
- 基于评论的推荐系统综述
- 手机配指环条码阅读器的爱恨纠缠
- Eclipse 使用中一些好用的快捷键
- 清除H5的浏览器缓存
- 【探花交友】阿里云OSS、百度人脸识别
- 速腾雷达录包方法(32线)
- Python 字典:当索引不好用时
- 《嫌疑人X的献身》读书笔记
- 国内下载vscode速度慢问题解决