国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

不用淘寶客api如何做網(wǎng)站網(wǎng)站制作 網(wǎng)站建設(shè)

不用淘寶客api如何做網(wǎng)站,網(wǎng)站制作 網(wǎng)站建設(shè),長春企業(yè)網(wǎng)站排名優(yōu)化,建設(shè)網(wǎng)站草案一、為什么要線程同步 因為當(dāng)我們有多個線程要同時訪問一個變量或?qū)ο髸r,如果這些線程中既有讀又有寫操作時,就會導(dǎo)致變量值或?qū)ο蟮臓顟B(tài)出現(xiàn)混亂,從而導(dǎo)致程序異常。舉個例子,如果一個銀行賬戶同時被兩個線程操作,一個…

一、為什么要線程同步

? ? ?因為當(dāng)我們有多個線程要同時訪問一個變量或?qū)ο髸r,如果這些線程中既有讀又有寫操作時,就會導(dǎo)致變量值或?qū)ο蟮臓顟B(tài)出現(xiàn)混亂,從而導(dǎo)致程序異常。舉個例子,如果一個銀行賬戶同時被兩個線程操作,一個取100塊,一個存錢100塊。假設(shè)賬戶原本有0塊,如果取錢線程和存錢線程同時發(fā)生,會出現(xiàn)什么結(jié)果呢?取錢不成功,賬戶余額是100.取錢成功了,賬戶余額是0.那到底是哪個呢?很難說清楚。因此多線程同步就是要解決這個問題。

二、不同步時的代碼

Bank.java

復(fù)制代碼
package threadTest;  /** * @author lixiaoxi * */  
public class Bank {  private int count =0;//賬戶余額  //存錢  public  void addMoney(int money){  count +=money;  System.out.println(System.currentTimeMillis()+"存進:"+money);  }  //取錢  public  void subMoney(int money){  if(count-money < 0){  System.out.println("余額不足");  return;  }  count -=money;  System.out.println(+System.currentTimeMillis()+"取出:"+money);  }  //查詢  public void lookMoney(){  System.out.println("賬戶余額:"+count);  }  
}
復(fù)制代碼

SyncThreadTest.java

復(fù)制代碼
package threadTest;  public class SyncThreadTest {  public static void main(String args[]){  final Bank bank=new Bank();  Thread tadd=new Thread(new Runnable() {  @Override  public void run() {  // TODO Auto-generated method stub  while(true){  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  // TODO Auto-generated catch block  
                        e.printStackTrace();  }  bank.addMoney(100);  bank.lookMoney();  System.out.println("\n");  }  }  });  Thread tsub = new Thread(new Runnable() {  @Override  public void run() {  // TODO Auto-generated method stub  while(true){  bank.subMoney(100);  bank.lookMoney();  System.out.println("\n");  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  // TODO Auto-generated catch block  
                        e.printStackTrace();  }     }  }  });  tsub.start();  tadd.start();  }  }
復(fù)制代碼

代碼很簡單,我就不解釋了,看看運行結(jié)果怎樣呢?截取了其中的一部分,是不是很亂,有些看不懂。

復(fù)制代碼
余額不足  
賬戶余額:0  余額不足  
賬戶余額:100  1441790503354存進:100  
賬戶余額:100  1441790504354存進:100  
賬戶余額:100  1441790504354取出:100  
賬戶余額:100  1441790505355存進:100  
賬戶余額:100  1441790505355取出:100  
賬戶余額:100
復(fù)制代碼

三、使用同步時的代碼

1、同步方法

即有synchronized關(guān)鍵字修飾的方法。?由于java的每個對象都有一個內(nèi)置鎖,當(dāng)用此關(guān)鍵字修飾方法時,內(nèi)置鎖會保護整個方法。在調(diào)用該方法前,需要獲得內(nèi)置鎖,否則就處于阻塞狀態(tài)。

修改后的Bank.java

復(fù)制代碼
/** * @author lixiaoxi* */  
public class Bank {  private int count =0;//賬戶余額  //存錢  public  synchronized void addMoney(int money){  count +=money;  System.out.println(System.currentTimeMillis()+"存進:"+money);  }  //取錢  public  synchronized void subMoney(int money){  if(count-money < 0){  System.out.println("余額不足");  return;  }  count -=money;  System.out.println(+System.currentTimeMillis()+"取出:"+money);  }  //查詢  public void lookMoney(){  System.out.println("賬戶余額:"+count);  }  
}
復(fù)制代碼

再看看運行結(jié)果:

復(fù)制代碼
余額不足  
賬戶余額:0  余額不足  
賬戶余額:0  1441790837380存進:100  
賬戶余額:100  1441790838380取出:100  
賬戶余額:0  1441790838380存進:100  
賬戶余額:100  1441790839381取出:100  
賬戶余額:0
復(fù)制代碼

瞬間感覺可以理解了吧。

注: synchronized關(guān)鍵字也可以修飾靜態(tài)方法,此時如果調(diào)用該靜態(tài)方法,將會鎖住整個類。

2、同步代碼塊

即有synchronized關(guān)鍵字修飾的語句塊。被該關(guān)鍵字修飾的語句塊會自動被加上內(nèi)置鎖,從而實現(xiàn)同步。

Bank.java代碼如下:

復(fù)制代碼
package threadTest;  package threadTest;  /** * @author lixiaoxi * */  
public class Bank {  private int count =0;//賬戶余額  //存錢  public void addMoney(int money){  synchronized (this) {  count +=money;  }  System.out.println(System.currentTimeMillis()+"存進:"+money);  }  //取錢  public void subMoney(int money){  synchronized (this) {  if(count-money < 0){  System.out.println("余額不足");  return;  }  count -=money;  }  System.out.println(+System.currentTimeMillis()+"取出:"+money);  }  //查詢  public void lookMoney(){  System.out.println("賬戶余額:"+count);  }  
}
復(fù)制代碼

運行結(jié)果如下:

復(fù)制代碼
余額不足  
賬戶余額:0  1441791806699存進:100  
賬戶余額:100  1441791806700取出:100  
賬戶余額:0  1441791807699存進:100  
賬戶余額:100
復(fù)制代碼

效果和方法一差不多。

注:同步是一種高開銷的操作,因此應(yīng)該盡量減少同步的內(nèi)容。通常沒有必要同步整個方法,使用synchronized代碼塊同步關(guān)鍵代碼即可。

3、使用特殊域變量(volatile)實現(xiàn)線程同步

(1)volatile關(guān)鍵字為域變量的訪問提供了一種免鎖機制;

(2)使用volatile修飾域相當(dāng)于告訴虛擬機該域可能會被其他線程更新;

(3)因此每次使用該域就要重新計算,而不是使用寄存器中的值;

(4)volatile不會提供任何原子操作,它也不能用來修飾final類型的變量。

Bank.java代碼如下:

復(fù)制代碼
package threadTest;  /** * @author lixiaoxi * */  
public class Bank {  private volatile int count = 0;// 賬戶余額  // 存錢  public void addMoney(int money) {  count += money;  System.out.println(System.currentTimeMillis() + "存進:" + money);  }  // 取錢  public void subMoney(int money) {  if (count - money < 0) {  System.out.println("余額不足");  return;  }  count -= money;  System.out.println(+System.currentTimeMillis() + "取出:" + money);  }  // 查詢  public void lookMoney() {  System.out.println("賬戶余額:" + count);  }  
}
復(fù)制代碼

運行效果怎樣呢?

復(fù)制代碼
余額不足  
賬戶余額:0  余額不足  
賬戶余額:100  1441792010959存進:100  
賬戶余額:100  1441792011960取出:100  
賬戶余額:0  1441792011961存進:100  
賬戶余額:100
復(fù)制代碼

是不是又看不懂了,又亂了。這是為什么呢?就是因為volatile不能保證原子操作導(dǎo)致的,因此volatile不能代替synchronized。此外volatile會組織編譯器對代碼優(yōu)化,因此能不使用它就不使用它吧。它的原理是每次要線程要訪問volatile修飾的變量時都是從內(nèi)存中讀取,而不是從緩存當(dāng)中讀取,因此每個線程訪問到的變量值都是一樣的。這樣就保證了同步。

?4、使用重入鎖實現(xiàn)線程同步

在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現(xiàn)了Lock接口的鎖,?它與使用synchronized方法和塊具有相同的基本行為和語義,并且擴展了其能力。
ReenreantLock類的常用方法有:
ReentrantLock() :創(chuàng)建一個ReentrantLock實例
lock() :獲得鎖
unlock() :釋放鎖
注:ReentrantLock()還有一個可以創(chuàng)建公平鎖的構(gòu)造方法,但由于能大幅度降低程序運行效率,不推薦使用。

Bank.java代碼修改如下:

復(fù)制代碼
package threadTest;  import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock;  /** * @author lixiaoxi * */  
public class Bank {  private  int count = 0;// 賬戶余額  //需要聲明這個鎖  private Lock lock = new ReentrantLock();  // 存錢  public void addMoney(int money) {  lock.lock();//上鎖  try{  count += money;  System.out.println(System.currentTimeMillis() + "存進:" + money);  }finally{  lock.unlock();//解鎖  
        }  }  // 取錢  public void subMoney(int money) {  lock.lock();  try{  if (count - money < 0) {  System.out.println("余額不足");  return;  }  count -= money;  System.out.println(+System.currentTimeMillis() + "取出:" + money);  }finally{  lock.unlock();  }  }  // 查詢  public void lookMoney() {  System.out.println("賬戶余額:" + count);  }  
}
復(fù)制代碼

運行效果怎樣呢?

復(fù)制代碼
余額不足  
賬戶余額:0  余額不足  
賬戶余額:0  1441792891934存進:100  
賬戶余額:100  1441792892935存進:100  
賬戶余額:200  1441792892954取出:100  
賬戶余額:100
復(fù)制代碼

效果和前兩種方法差不多。

? ? ?如果synchronized關(guān)鍵字能滿足用戶的需求,就用synchronized,因為它能簡化代碼 。如果需要更高級的功能,就用ReentrantLock類,此時要注意及時釋放鎖,否則會出現(xiàn)死鎖,通常在finally代碼釋放鎖。

5、使用局部變量實現(xiàn)線程同步

Bank.java代碼如下:

復(fù)制代碼
package com.demo.test;/** * @author lixiaoxi* */ 
public class Bank {private static ThreadLocal<Integer> count = new ThreadLocal<Integer>(){  @Override  protected Integer initialValue() {  // TODO Auto-generated method stub  return 0;  }  };  // 存錢  public void addMoney(int money) {  count.set(count.get()+money);  System.out.println(System.currentTimeMillis() + "存進:" + money);  }  // 取錢  public void subMoney(int money) {  if (count.get() - money < 0) {  System.out.println("余額不足");  return;  }  count.set(count.get()- money);  System.out.println(+System.currentTimeMillis() + "取出:" + money);  }  // 查詢  public void lookMoney() {  System.out.println("賬戶余額:" + count.get());  }      
}
復(fù)制代碼

運行效果:

復(fù)制代碼
余額不足
賬戶余額:01511166594460存進:100
賬戶余額:200余額不足
賬戶余額:01511166595460存進:100
賬戶余額:300余額不足
賬戶余額:01511166596460存進:100
賬戶余額:400
復(fù)制代碼

看了運行效果,一開始一頭霧水,怎么只讓存,不讓取啊?看看ThreadLocal的原理:

? ? ?如果使用ThreadLocal管理變量,則每一個使用該變量的線程都獲得該變量的副本,副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變量副本,而不會對其他線程產(chǎn)生影響。現(xiàn)在明白了吧,原來每個線程運行的都是一個副本,也就是說存錢和取錢是兩個賬戶,只是名字相同而已。所以就會發(fā)生上面的效果。

ThreadLocal與同步機制

a.ThreadLocal與同步機制都是為了解決多線程中相同變量的訪問沖突問題;

b.前者采用以”空間換時間”的方法,后者采用以”時間換空間”的方式。

http://m.aloenet.com.cn/news/1238.html

相關(guān)文章:

  • 銀川做企業(yè)網(wǎng)站合肥seo報價
  • 重慶網(wǎng)站建設(shè)設(shè)計網(wǎng)絡(luò)營銷十大成功案例
  • 娛樂網(wǎng)站開發(fā)福州外包seo公司
  • 榮耀手機商城官方網(wǎng)站入口西安seo排名外包
  • 蘇州網(wǎng)站建設(shè)的一般流程職業(yè)技能培訓(xùn)網(wǎng)
  • 哪家做網(wǎng)站靠譜企業(yè)營銷策劃
  • 福清網(wǎng)站建設(shè)百度收錄批量提交入口
  • 海門做網(wǎng)站自動優(yōu)化句子的軟件
  • 數(shù)據(jù)分析師簡歷襄陽網(wǎng)站推廣優(yōu)化技巧
  • 北京住房城鄉(xiāng)建設(shè)部網(wǎng)站八大員千萬不要去電商公司上班
  • 可以在哪些網(wǎng)站做翻譯兼職建立企業(yè)網(wǎng)站步驟
  • 天津平臺網(wǎng)站建設(shè)推薦廣告營銷平臺
  • 成都旅游景點攻略自由行攻略關(guān)鍵詞優(yōu)化seo公司
  • 西安微網(wǎng)站建設(shè)百度一下 你就知道官網(wǎng)
  • 網(wǎng)站開發(fā)需要考什么證網(wǎng)絡(luò)營銷渠道有哪三類
  • 南陽做網(wǎng)站的公怎樣進行網(wǎng)絡(luò)營銷吸引顧客
  • 商標(biāo)被注冊了做網(wǎng)站國外網(wǎng)站推廣公司
  • 建筑工程外架安全網(wǎng)西安的網(wǎng)絡(luò)優(yōu)化公司
  • 做算法題的 網(wǎng)站成品網(wǎng)站貨源1
  • 網(wǎng)站建設(shè)策劃實訓(xùn)總結(jié)友情鏈接怎么連
  • 遵義新藍外國語學(xué)校網(wǎng)站建設(shè)臺州seo優(yōu)化
  • 郴州北湖區(qū)疫情最新消息網(wǎng)站優(yōu)化
  • 建設(shè)企業(yè)網(wǎng)站進去無法顯示怎么在百度上免費做廣告
  • 如何通過做網(wǎng)站月入上萬廣州seo公司品牌
  • 溫州建設(shè)網(wǎng)站百度上??偛?/a>
  • 天津企商網(wǎng)站建設(shè)公司關(guān)鍵詞優(yōu)化按天計費
  • 網(wǎng)站如何做銀聯(lián)在線支付大連中小企業(yè)網(wǎng)絡(luò)營銷
  • 一般做外貿(mào)上什么網(wǎng)站熱狗網(wǎng)站排名優(yōu)化外包
  • 建設(shè)網(wǎng)站com艾滋病阻斷藥
  • 網(wǎng)站robots.txt檢測網(wǎng)站關(guān)鍵詞在線優(yōu)化