TIP
Java提供的Runnable接口中的run方法是启动线程的核心
Thread类中包含了丰富的线程操作方法,不过它也是通过实现Runnable接口来创建线程的
# synchronized是锁定对象,而不是锁定代码的
- 普通方法锁定this对象
- 静态方法锁定类对象
- 代码快锁定指定对象
锁定的对象就是一把锁头,想进屋子里执行代码,就先搞定锁 ``
package com.mrzhang.javalearn.bingfa.demo_02;
/**
* Synchronized基本使用(一)
* <p>
* synchronized并不锁定方法,而是锁定对象
* 默认是锁定this对象,静态方法默认锁定.class
*
* @author 91MrZhang on 2020/7/31
*/
public class SynchronizedDemo01 {
public /*synchronized*/ void printMsg(String threadName) {
System.out.println(threadName + "开始执行");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "执行完毕");
}
public static void main(String[] args) {
SynchronizedDemo01 sd01 = new SynchronizedDemo01();
for (int i = 0; i < 5; i++) {
new Thread(() -> sd01.printMsg(Thread.currentThread().getName()), "线程" + i).start();
}
}
}
# 锁住自定义对象时,不要切换引用地址
package com.mrzhang.javalearn.bingfa.demo_02;
/**
* Synchronized基本使用(二)
* <p>
* 1. 手动锁定new出来的lock对象,所以锁是在堆里的,代码规范,锁对象都是需要加final的,如果Lock指向一个新new的对象的话,那么lock会失效
* 2. 在方法中某一个部分加synchronized,比给整个方法都加synchronized效率要高一些
*
* @author 91MrZhang on 2020/7/31
*/
public class SynchronizedDemo02 {
private /*final*/ Object lock = new Object();
public void printMsg(String threadName) {
synchronized (lock) {
System.out.println(threadName + "开始执行");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "执行完毕");
}
}
public static void main(String[] args) {
SynchronizedDemo02 sd01 = new SynchronizedDemo02();
for (int i = 0; i < 5; i++) {
new Thread(() -> {
//锁失效的情况
//sd01.lock = new Object();
sd01.printMsg(Thread.currentThread().getName());
},"线程" + i).start();
}
}
}
这里需要提到Java对象的内存模型(Markword中的信息),具体细节不在这里讲述了
# 静态方法不能sychronized this对象
/**
* Synchronized基本使用(三)
* <p>
* 静态方法加锁,就不能用this了,需要用.class
*
* @author 91MrZhang on 2020/7/31
*/
public class SynchronizedDemo03 {
public static void printMsg(String msg) {
// 如果是this,编译器直接不通过
// synchronized (this) {
synchronized (SynchronizedDemo03.class) {
System.out.println("嘿嘿嘿");
}
}
}