最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java多線程編程之Synchronized塊同步方法

 更新時(shí)間:2015年12月02日 15:05:50   投稿:lijiao  
這篇文章主要介紹了java多線程編程之Synchronized塊同步方法,synchronized關(guān)鍵字又稱同步鎖,當(dāng)方法執(zhí)行完后,會(huì)自動(dòng)釋放鎖鎖,只有一個(gè)線程能進(jìn)入此方法,看看下文中各種例子對(duì)synchronized的詳細(xì)解釋

文章分享了4個(gè)例子對(duì)synchronized的詳細(xì)解釋

1、是否加synchronized關(guān)鍵字的不同

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();

    Thread t1 = new Thread1(example);
    Thread t2 = new Thread1(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }

  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

加了synchronized關(guān)鍵字的輸出結(jié)果如下

會(huì)先輸出一組0-4,接著再輸出下一組,兩個(gè)線程順序執(zhí)行

excute:0
excute:1
excute:2
excute:3
excute:4
excute:0
excute:1
excute:2
excute:3
excute:4

沒加synchronized關(guān)鍵字的輸出結(jié)果如下

兩個(gè)線程同時(shí)執(zhí)行excute方法,同時(shí)并發(fā)的

excute:0
excute:0
excute:1
excute:1
excute:2
excute:2
excute:3
excute:3
excute:4
excute:4

2、多個(gè)方法的多線程情況

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();

    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }
  }
  public synchronized void excute1() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute1:" + i);
    }
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

執(zhí)行結(jié)果如下

同樣是順序執(zhí)行,執(zhí)行完一個(gè)線程再執(zhí)行另一個(gè)線程

excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4

如果去掉synchronized關(guān)鍵字,則兩個(gè)方法并發(fā)執(zhí)行,并沒有相互影響。

但是如例子程序中所寫,即便是兩個(gè)方法:

執(zhí)行結(jié)果永遠(yuǎn)是執(zhí)行完一個(gè)線程的輸出再執(zhí)行另一個(gè)線程的?! ?/p>

說明:

  如果一個(gè)對(duì)象有多個(gè)synchronized方法,某一時(shí)刻某個(gè)線程已經(jīng)進(jìn)入到了某個(gè)synchronized方法,那么在該方法沒有執(zhí)行完畢前,其他線程是無法訪問該對(duì)象的任何synchronized方法的。

結(jié)論:

  當(dāng)synchronized關(guān)鍵字修飾一個(gè)方法的時(shí)候,該方法叫做同步方法。

  Java中的每個(gè)對(duì)象都有一個(gè)鎖(lock),或者叫做監(jiān)視器(monitor),當(dāng)一個(gè)線程訪問某個(gè)對(duì)象的synchronized方法時(shí),將該對(duì)象上鎖,其他任何線程都無法再去訪問該對(duì)象的synchronized方法了(這里是指所有的同步方法,而不僅僅是同一個(gè)方法),直到之前的那個(gè)線程執(zhí)行方法完畢后(或者是拋出了異常),才將該對(duì)象的鎖釋放掉,其他線程才有可能再去訪問該對(duì)象的synchronized方法。

  注意這時(shí)候是給對(duì)象上鎖,如果是不同的對(duì)象,則各個(gè)對(duì)象之間沒有限制關(guān)系。

  嘗試在代碼中構(gòu)造第二個(gè)線程對(duì)象時(shí)傳入一個(gè)新的Example對(duì)象,則兩個(gè)線程的執(zhí)行之間沒有什么制約關(guān)系。

3、靜態(tài)的同步方法

當(dāng)一個(gè)synchronized關(guān)鍵字修飾的方法同時(shí)又被static修飾,之前說過,非靜態(tài)的同步方法會(huì)將對(duì)象上鎖,但是靜態(tài)方法不屬于對(duì)象,而是屬于類,它會(huì)將這個(gè)方法所在的類的Class對(duì)象上鎖。

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();
    Example example2 = new Example();
    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example2);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized static void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }
  }
  public synchronized static void excute1() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute1:" + i);
    }
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

執(zhí)行結(jié)果如下

excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4

如果沒有static修飾符,兩個(gè)線程分別傳入不同的對(duì)象,則會(huì)同時(shí)并發(fā)執(zhí)行

所以如果是靜態(tài)方法的情況(execute()和execute2()都加上static關(guān)鍵字),即便是向兩個(gè)線程傳入不同的Example對(duì)象,這兩個(gè)線程仍然是互相制約的,必須先執(zhí)行完一個(gè),再執(zhí)行下一個(gè)。

結(jié)論:

  如果某個(gè)synchronized方法是static的,那么當(dāng)線程訪問該方法時(shí),它鎖的并不是synchronized方法所在的對(duì)象,而是synchronized方法所在的類所對(duì)應(yīng)的Class對(duì)象。Java中,無論一個(gè)類有多少個(gè)對(duì)象,這些對(duì)象會(huì)對(duì)應(yīng)唯一一個(gè)Class對(duì)象,因此當(dāng)線程分別訪問同一個(gè)類的兩個(gè)對(duì)象的兩個(gè)static,synchronized方法時(shí),它們的執(zhí)行順序也是順序的,也就是說一個(gè)線程先去執(zhí)行方法,執(zhí)行完畢后另一個(gè)線程才開始。

4.synchronized塊

synchronized(object)

{     

}

表示線程在執(zhí)行的時(shí)候會(huì)將object對(duì)象上鎖。(注意這個(gè)對(duì)象可以是任意類的對(duì)象,也可以使用this關(guān)鍵字)。

這樣就可以自行規(guī)定上鎖對(duì)象。

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();
    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public void excute() {
    synchronized (this) {
      for (int i = 0; i < 5; ++i) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("excute:" + i);
      }
    }
    
  }
  public void excute1() {
    synchronized (this) {
      for (int i = 0; i < 5; ++i) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("excute1:" + i);
      }
    }
    
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

執(zhí)行結(jié)果如下

excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4

例子程序4所達(dá)到的效果和例子程序2的效果一樣,都是使得兩個(gè)線程的執(zhí)行順序進(jìn)行,而不是并發(fā)進(jìn)行,當(dāng)一個(gè)線程執(zhí)行時(shí),將object對(duì)象鎖住,另一個(gè)線程就不能執(zhí)行對(duì)應(yīng)的塊。

synchronized方法實(shí)際上等同于用一個(gè)synchronized塊包住方法中的所有語句,然后在synchronized塊的括號(hào)中傳入this關(guān)鍵字。當(dāng)然,如果是靜態(tài)方法,需要鎖定的則是class對(duì)象。  

可能一個(gè)方法中只有幾行代碼會(huì)涉及到線程同步問題,所以synchronized塊比synchronized方法更加細(xì)粒度地控制了多個(gè)線程的訪問,只有synchronized塊中的內(nèi)容不能同時(shí)被多個(gè)線程所訪問,方法中的其他語句仍然可以同時(shí)被多個(gè)線程所訪問(包括synchronized塊之前的和之后的)。

結(jié)論:

  synchronized方法是一種粗粒度的并發(fā)控制,某一時(shí)刻,只能有一個(gè)線程執(zhí)行該synchronized方法;

  synchronized塊則是一種細(xì)粒度的并發(fā)控制,只會(huì)將塊中的代碼同步,位于方法內(nèi)、synchronized塊之外的其他代碼是可以被多個(gè)線程同時(shí)訪問到的。

以上就是關(guān)于java多線程編程Synchronized塊同步方法,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • 詳解Java如何優(yōu)雅的處理異常

    詳解Java如何優(yōu)雅的處理異常

    在編寫 Java 程序的過程中,有一種異常幾乎每個(gè)開發(fā)者都會(huì)遇到——空指針異常(NullPointerException),那么我們應(yīng)該如何有效且優(yōu)雅的處理空指針異常呢,下面小編就來詳細(xì)介紹這個(gè)處理方案吧
    2023-08-08
  • MybatisPlus實(shí)現(xiàn)對(duì)象嵌套關(guān)聯(lián)查詢一對(duì)多List集合查詢

    MybatisPlus實(shí)現(xiàn)對(duì)象嵌套關(guān)聯(lián)查詢一對(duì)多List集合查詢

    這篇文章主要介紹了MybatisPlus實(shí)現(xiàn)對(duì)象嵌套關(guān)聯(lián)查詢一對(duì)多List集合查詢,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Windows系統(tǒng)中Java調(diào)用cmd命令及執(zhí)行exe程序的方法

    Windows系統(tǒng)中Java調(diào)用cmd命令及執(zhí)行exe程序的方法

    這篇文章主要介紹了Windows系統(tǒng)中Java調(diào)用cmd命令及執(zhí)行exe程序的方法,主要用到了IOException類,需要的朋友可以參考下
    2016-03-03
  • SpringBoot配置默認(rèn)HikariCP數(shù)據(jù)源

    SpringBoot配置默認(rèn)HikariCP數(shù)據(jù)源

    咱們開發(fā)項(xiàng)目的過程中用到很多的開源數(shù)據(jù)庫鏈接池,比如druid、c3p0、BoneCP等等,本文主要介紹了SpringBoot配置默認(rèn)HikariCP數(shù)據(jù)源,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 一文告訴你為什么要重寫hashCode()方法和equals()方法

    一文告訴你為什么要重寫hashCode()方法和equals()方法

    本篇文章帶大家了解一下為什么重寫hashCode()方法和equals()方法,文中有非常詳細(xì)的說明以及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • 一文搞懂Spring中的Bean作用域

    一文搞懂Spring中的Bean作用域

    scope用來聲明容器中的對(duì)象所應(yīng)該處的限定場(chǎng)景或者說該對(duì)象的存活時(shí)間,即容器在對(duì)象進(jìn)入其 相應(yīng)的scope之前,生成并裝配這些對(duì)象,在該對(duì)象不再處于這些scope的限定之后,容器通常會(huì)銷毀這些對(duì)象,這篇文章主要介紹了Spring中的Bean作用域,需要的朋友可以參考下
    2022-06-06
  • 簡(jiǎn)單了解SpringBoot HATEOAS使用方法

    簡(jiǎn)單了解SpringBoot HATEOAS使用方法

    這篇文章主要介紹了簡(jiǎn)單了解SpringBoot HATEOAS使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java的遞歸算法詳解

    Java的遞歸算法詳解

    Java遞歸算法是基于Java語言實(shí)現(xiàn)的遞歸算法。遞歸算法對(duì)解決一大類問題很有效,它可以使算法簡(jiǎn)潔和易于理解。接下來通過本文給大家介紹Java遞歸算法相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧
    2021-09-09
  • Java中Cglib代理類重寫邏輯詳解

    Java中Cglib代理類重寫邏輯詳解

    這篇文章主要介紹了Java中Cglib代理類重寫邏輯詳解,代理類中只會(huì)維護(hù)NoOp這個(gè)回調(diào)屬性,并不會(huì)生成目標(biāo)類MyService中的noOp所對(duì)應(yīng)的方法,需要的朋友可以參考下
    2023-11-11
  • Servlet實(shí)現(xiàn)文件下載功能

    Servlet實(shí)現(xiàn)文件下載功能

    這篇文章主要為大家詳細(xì)介紹了Servlet實(shí)現(xiàn)文件下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12

最新評(píng)論

佛冈县| 家居| 南汇区| 慈利县| 视频| 镇康县| 清远市| 唐海县| 潮安县| 琼中| 山东省| 淅川县| 迁西县| 庆元县| 井冈山市| 理塘县| 家居| 南开区| 新巴尔虎右旗| 密云县| 开鲁县| 北川| 喀喇| 专栏| 兴文县| 黄浦区| 新源县| 大竹县| 长汀县| 崇礼县| 虞城县| 五峰| 彭泽县| 历史| 那坡县| 克什克腾旗| 东辽县| 北海市| 高尔夫| 基隆市| 长沙市|