第一组
package com.chen.lock8;
import java.util.concurrent.TimeUnit;
/**
* 8 锁,就是关于锁的8个问题
* 1、标准情况下,两个线程先打印 打电话 还是 发短信? 1.发短 2.打电话
* 2、sendSms延迟4秒,两个线程先打印 打电话 还是 发短信?
*/
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendMs();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
// synchronized 锁的对象是方法的调用者!
// 两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendMs(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
第二组
package com.chen.lock8;
import java.util.concurrent.TimeUnit;
/**
* 3.增加了一个普通方法后,发短信还是hello? 普通方法
* 4.两个对象,两个是同步方法,先发短信还是打电话? 打电话
*/
public class Test2 {
public static void main(String[] args) {
// 两个对象,两个调用者,两把锁!
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
new Thread(()->{
phone1.sendMs();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone2{
// synchronized 锁的对象是方法的调用者!
public synchronized void sendMs(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
// 这里没有锁!不是同步方法,不受锁的影响
public void hello(){
System.out.println("hello");
}
}
第三组
package com.chen.lock8;
import java.util.concurrent.TimeUnit;
/**
* 5、增加两个静态的同步方法,只有一个对象,先打印打电话还是发短信
* 6、两个对象,增加两个静态的同步方法,先打印打电话还是发短信
*/
public class Test3{
public static void main(String[] args) {
// 两个对象的Class类模板只有一个,static,锁的是class
Phone3 phone = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(()->{
phone.sendMs();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
// Phone3只有一个class对象
class Phone3{
// synchronized 锁的对象是方法的调用者!
// static 静态方法
// 类一加载就有了!锁的是class
public static synchronized void sendMs(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
第四组
package com.chen.lock8;
import java.util.concurrent.TimeUnit;
/**
* 7、一个静态同步方法,一个普通同步方法 一个对象 先答应 发短信还是打电话
* 8、一个静态同步方法,一个普通同步方法 两个对象 先答应 发短信还是打电话
*/
public class Test4{
public static void main(String[] args) {
// 两个对象的Class类模板只有一个,static,锁的是class
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
new Thread(()->{
phone1.sendMs();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
// Phone3只有一个class对象
class Phone4{
// 静态同步方法 锁的死Class模板
public static synchronized void sendMs(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
// 普通同步方法 所得是调用者
public synchronized void call(){
System.out.println("打电话");
}
}
小结:
new this 具体的一个手机
stati Class 唯一的一个模板
本文通过四个Java代码示例,深入讲解了synchronized锁的使用、对象锁与类锁的区别,以及普通方法与同步方法在并发情况下的行为。从Test1到Test4,逐步揭示了并发环境中的短信、电话调用顺序变化规律。

1593

被折叠的 条评论
为什么被折叠?



