public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
/*
* 在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,
* 便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
* 上面的代码中c和d的数值为3,因此会直接从cache中取已经存在的对象,
* 所以c和d指向的是同一个对象,而e和f则是分别指向不同的对象。
*/
System.out.println(c==d); //true
System.out.println(e==f); //false
/*
* 当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,
* 而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。
* 另外,对于包装器类型,equals方法并不会进行类型转换。
*/
System.out.println(c==(a+b)); //true
System.out.println(c.equals(a+b)); //true
System.out.println(g==(a+b));
/*
* 如果数值是int类型的,装箱过程调用的是Integer.valueOf;
* 如果是long类型的,装箱调用的Long.valueOf方法
*/
System.out.println(g.equals(a+b)); //false
System.out.println(g.equals(a+h)); //true
}
}
public class JDBCUtils {
public void demo1() {
//获得连接(工具类里会先注册驱动)
Connection conn = null;
//conn连接数据库获得语句执行者psmt
PreparedStatement psmt = null;
//psmt执行后获得结果集rs
ResultSet rs =null;
try {
conn = JDBCUtils.getConnection();
String sql = "select * from category";
psmt = conn.prepareStatement(sql);
rs = psmt.executeQuery();
while(rs.next()) {
System.out.println(rs.getInt("cid")+"---"+rs.getString("cname"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(rs, psmt, conn);
}
}
//添加
@Test
public void demo2() {
Connection conn = null;
PreparedStatement psmt = null;
ResultSet rs =null;
try {
//获得连接
conn = JDBCUtils.getConnection();
//获得语句执行者
String sql = "insert into category values (null,?)";
psmt = conn.prepareStatement(sql);
//设置参数
psmt.setString(1, "bag");
int i = psmt.executeUpdate();
if(i > 0) {
System.out.println("添加成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(rs, psmt, conn);
}
}
//修改
@Test
public void demo3() {
Connection conn = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
//获得连接
conn = JDBCUtils.getConnection();
//psmt语句执行者
String sql = "update category set cname = ? where cid = ?";
psmt = conn.prepareStatement(sql);
psmt.setString(1, "shoes");
psmt.setInt(2, 5);
int i = psmt.executeUpdate();
if(i > 0) {
System.out.println("修改成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(rs, psmt, conn);
}
}
//删除
@Test
public void demo4() {
Connection conn = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
//获得连接
conn = JDBCUtils.getConnection();
//psmt语句执行者
String sql = "delete from category where cid = ?";
psmt = conn.prepareStatement(sql);
psmt.setInt(1, 5);
int i = psmt.executeUpdate();
if(i > 0) {
System.out.println("删除成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(rs, psmt, conn);
}
}
}
1. 共享锁(S锁)/排他锁(X锁)
2. 意向锁
3. 插入意向锁(insert intention looks)
- 插入意向锁是间隙锁的一种,针对insert操作产生。目的是提高插入并发。
- 多个事物,在同一个索引,同一个范围区间进行插入记录的时候,如果 插入的位置不冲突,不会阻塞彼此。
4. 记录锁
- 对单条索引记录进行加锁,锁住的是索引记录而非记录本身,即使表中没有任何索引,MySQL会自动创建一个隐式的row_id作为聚集索引来进行加锁。
5. 间隙锁(gap锁)
- 封锁记录中的间隔,防止间隔中被其他事务插入。
- 间隙锁主要出现在RR隔离级别,避免出现幻读。
6. 临键锁(Next-Key Locks)
- 临键锁是记录锁和间隙锁的组合,既锁住了记录也锁住了范围。
- 临键锁的主要目的,也是为了避免幻读。
- 如果把事务的隔离级别降级为RC,临键锁就也会失效。
7. 自增长锁: 自增长锁是一种表级锁,专门针对auto_increment类型的列。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
1. 新建(New): 新创建一个线程对象。
2. 可运行(Runnable): 对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3. 运行(Running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
4. 阻塞(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
5. 死亡(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
synchronized关键字修饰普通方法时,获得的锁是对象锁,也就是this。而修饰静态方法时,锁是类锁,也就是类名.class。
public class TicketsTest {
public static void main(String[] args) {
//创建Runnable对象
TicketsSale ts = new TicketsSale();
//创建线程对象
Thread t1 = new Thread(ts);
t1.setName("窗口1");
Thread t2 = new Thread(ts);
t2.setName("窗口2");
Thread t3 = new Thread(ts);
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
public class TicketsSale implements Runnable {
static int tickets = 100;
//创建锁对象
Object obj = new Object();
@Override
public void run() {
while(true) {
synchronized (obj) {
if(tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+tickets--);
}
}
}
}
}
JVM内存模型
在下面这段程序中:
public void test1() {
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
/*
* 如果是Stringx="abc";编译器首先会在常量池中寻找有没有"abc"这个字符串,
* 如果有则直接从常量池中取,不会new,
* 如果没有则在常量池中创建一个此字符串对象,
* 然后堆中再创建一个常量池中此“abc”对象的拷贝对象
*/
System.out.println(str1 == str2); //true
System.out.println(str1 == str3); //false
System.out.println(str3 == str4); //false
//equals比较的是值
System.out.println(str1.equals(str2)); //true
System.out.println(str1.equals(str3)); //true
}
//JS
var myElement = document.getElementById("id01");
//JQuery
var myElement = $("#id01");
//JS
var myElements = document.getElementsByTagName("p");
//JQuery
var myElements = $("p");
//JS
var myElements = document.getElementsByClassName("intro");
//JQuery
var myElements = $(".intro");