資源類:電話,有發短信與打電話的功能。
class Phone
{
public void send() throws InterruptedException
{
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public void call()
{
System.out.println("打電話");
}
}
1、電話類中的方法都用synchronized修飾,並且只實例化一個對象Phone phone = new Phone();
,此時線程拿到的鎖是phone的對象鎖,每個對象有一把鎖,多個線程使用同一個對象,多個線程就是使用一把鎖,先調用的先執行!
package juc;
import java.util.concurrent.TimeUnit;
/**
* @program: relearn
* @description:
* @author: qinda
* @create: 2020-05-09 12:36
**/
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
try {
phone.send();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
public synchronized void send() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public synchronized void call()
{
System.out.println("打電話");
}
}
//發短信
//打電話
2、現在在Phone中新增方法public void hello()
,不使用synchronized修飾,此時如果有線程調用hello方法,將不會考慮鎖的問題,也不會阻塞,因爲這個方法並不是同步方法。多個線程,有的線程有鎖,有的線程沒鎖,兩者之間不存在競爭同一把鎖的情況,先後執行順序是隨機的。
package juc;
import java.util.concurrent.TimeUnit;
/**
* @program: relearn
* @description:
* @author: qinda
* @create: 2020-05-09 12:36
**/
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
try {
phone.send();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.call();
},"B").start();
new Thread(()->{
phone.hello();
},"C").start();
}
}
class Phone{
public synchronized void send() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public synchronized void call()
{
System.out.println("打電話");
}
public void hello()
{
System.out.println("hello");
}
}
//hello
//發短信
//打電話
3、現在聲明兩個Phone對象
Phone phone = new Phone();
Phone phone2 = new Phone();
因爲每個對象都有一把鎖,所以兩個線程競爭的不是同一把鎖,所以不存在競爭關係
①被 synchronized 修飾的方法,鎖的對象是方法的調用者;
②調用者不同,它們之間用的不是同一個鎖,相互之間沒有關係。
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
try {
phone.send();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone{
public synchronized void send() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public synchronized void call()
{
System.out.println("打電話");
}
}
//打電話
//發短信
4、現在將兩個方法都加上static修飾被 synchronized 和 static 同時修飾的方法,鎖的對象是類的 class 對象,是唯一的一把鎖。線程之間是順序執行。
鎖Class和鎖對象的區別:
1、Class 鎖 ,類模版,只有一個;
2、對象鎖 , 通過類模板可以new 多個對象。
如果全部都鎖了Class,那麼這個類下的所有對象都具有同一把鎖。
package juc;
import java.util.concurrent.TimeUnit;
/**
* @program: relearn
* @description:
* @author: qinda
* @create: 2020-05-09 12:36
**/
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
try {
phone.send();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
public static synchronized void send() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public static synchronized void call()
{
System.out.println("打電話");
}
}
//發短信
//打電話
五、被 synchronized 修飾 和 static 修飾的方法,鎖的對象是類的 class 對象,是唯一的一把鎖。
Class鎖是唯一的,所以多個對象使用的也是同一個Class鎖。
package juc;
import java.util.concurrent.TimeUnit;
/**
* @program: relearn
* @description:
* @author: qinda
* @create: 2020-05-09 12:36
**/
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
Phone phone1 = new Phone();
new Thread(()->{
try {
phone.send();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone1.call();
},"B").start();
}
}
class Phone{
public static synchronized void send() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public static synchronized void call()
{
System.out.println("打電話");
}
}
//發短信
//打電話
六、被 synchronized和static修飾的方法,鎖的對象是類的class對象!唯一的同一把鎖;
只被synchronized修飾的方法,是普通鎖(如對象鎖),不是Class鎖,所以進程之間執行順序互不干擾。
package juc;
import java.util.concurrent.TimeUnit;
/**
* @program: relearn
* @description:
* @author: qinda
* @create: 2020-05-09 12:36
**/
public class Test1 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
try {
phone.send();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
public static synchronized void send() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("發短信");
}
public synchronized void call()
{
System.out.println("打電話");
}
}
//打電話
//發短信