亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

貓頭鷹的深夜翻譯:理解java的classloader

Eminjannn / 2169人閱讀

摘要:它們是通過來自遠(yuǎn)程的服務(wù)器的連接發(fā)送字節(jié)碼并在本地運(yùn)行,這一點(diǎn)令人興奮。中有一個(gè)自定義的,它不是從本地文件系統(tǒng)加載類文件,而是從遠(yuǎn)程服務(wù)器上獲取,通過加載原始字節(jié)碼,再在中轉(zhuǎn)化為類。它將字節(jié)碼解析為運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu),檢查其有效性等。

前言

Java ClassLoader是java運(yùn)行系統(tǒng)中一個(gè)至關(guān)重要但是經(jīng)常被忽略的組件。它負(fù)責(zé)在運(yùn)行時(shí)尋找并加載類文件。創(chuàng)建自定義的ClassLoader可以徹底重定義如何將類文件加載至系統(tǒng)。

這個(gè)教程對Java的ClassLoader進(jìn)行總體概述,并給了一個(gè)自定義ClassLoader的例子。這個(gè)ClassLoader會(huì)在加載代碼之前自動(dòng)編譯。你將會(huì)了解ClassLoader是做什么的,以及如何創(chuàng)建自定義ClassLoader。

本教程需要閱讀者對Java編程有基礎(chǔ)了解,包括創(chuàng)建,編譯和執(zhí)行簡單的命令行Java程序。

閱讀完本教程之后,你會(huì)知道如何:

擴(kuò)展JVM的功能

創(chuàng)建一個(gè)自定義的ClassLoader

學(xué)習(xí)如何將ClassLoader集成至Java應(yīng)用

修改ClassLoader使其符合Java2版本

什么是ClassLoader

在所有的編程語言中,Java以運(yùn)行在Java虛擬機(jī)上而獨(dú)樹一幟。這意味著編譯的程序?qū)⒁砸环N獨(dú)特的,與平臺(tái)無關(guān)的形式運(yùn)行在目標(biāo)機(jī)器上,而不是目標(biāo)機(jī)器的格式。這種格式在很多方面和傳統(tǒng)的可執(zhí)行程序相比,有很大的區(qū)別。

Java程序與C或C++程序最大的不同在于,它不是單個(gè)可執(zhí)行文件,而是由許多多帶帶的類文件構(gòu)成,每個(gè)類文件對應(yīng)一個(gè)Java類。

不僅如此,這些類文件并不是一次性加載到內(nèi)存的,而是按需加載的。ClassLoader是JVM的一部分,它將類加載到內(nèi)存中。

此外,Java ClassLoader是用Java編寫的。這意味著可以輕松的創(chuàng)建自己的ClassLoader,無需了解JVM更多的細(xì)節(jié)。

為什么編寫ClassLoader

如果JVM已經(jīng)有一個(gè)ClassLoader了,為什么還要再寫一個(gè)?好問題,默認(rèn)的ClassLoader只知道如何從本地的文件系統(tǒng)中加載類文件。一般場景下,當(dāng)你在本地編寫代碼并且在本地編譯時(shí),完全足夠了。

但是,JAVA語言最新穎的特點(diǎn)之一就是可以從本地硬盤或是互聯(lián)網(wǎng)之外的地方獲取類。比如,瀏覽器使用自定義的ClassLoader從網(wǎng)站上獲取可執(zhí)行內(nèi)容。

還有很多其它獲取類文件的方法。除了從本地或是網(wǎng)上加載類文件,還可以用類加載器來:

在執(zhí)行不受信任的代碼之前自動(dòng)驗(yàn)證數(shù)字簽名

使用用戶提供的密碼透明的解密代碼

根據(jù)用戶的特定需求創(chuàng)建自定義的動(dòng)態(tài)類

任何生成Java字節(jié)碼的內(nèi)容都可以集成到你的應(yīng)用程序中去。

自定義ClassLoader的例子

如果你曾經(jīng)使用過applet,你肯定用到了一個(gè)自定義的類加載器。

在Sun發(fā)布Java語言的時(shí)候,最令人興奮的事情之一就是觀察這項(xiàng)技術(shù)是如何執(zhí)行從遠(yuǎn)程Web服務(wù)器及時(shí)加載代碼的。它們是通過來自遠(yuǎn)程的Web服務(wù)器的HTTP連接發(fā)送字節(jié)碼并在本地運(yùn)行,這一點(diǎn)令人興奮。

Java語言支持自定義ClassLoader的功能使這一想法成為可能。applet中有一個(gè)自定義的ClassLoader,它不是從本地文件系統(tǒng)加載類文件,而是從遠(yuǎn)程Web服務(wù)器上獲取,通過Http加載原始字節(jié)碼,再在jvm中轉(zhuǎn)化為類。

瀏覽器和Applet中的類加載器還有別的功能:安全管理,防止不同頁面上的applet相互影響等。

下面我們將會(huì)創(chuàng)建一個(gè)自定義的類加載器叫做CompilingClassLoader(CCL)、CCL會(huì)幫我們編譯Java代碼。它基本上就像是在運(yùn)行系統(tǒng)中直接構(gòu)建一個(gè)簡單的make程序。

ClassLoader結(jié)構(gòu)

ClassLoader的基本目的是為類的請求提供服務(wù)。JVM需要一個(gè)類,于是它通過類的名字詢問ClassLoader來加載這個(gè)類。ClassLoader試著返回一個(gè)代表該類的對象。

通過覆蓋此過程不同階段對應(yīng)的方法,可以創(chuàng)建自定義的ClassLoader。

在本文的剩余部分,你會(huì)了解到ClassLoader中的一些關(guān)鍵方法。你會(huì)了解到每個(gè)方法的用途以及它在類加載過程中是如何調(diào)用的。你還會(huì)了解當(dāng)你在自定義ClassLoader時(shí)需要完成的工作。

loadClass方法##、

ClassLoader.loadClass()方法是ClassLoader的入口。它的方法標(biāo)簽如下:

Class loadClass(String name, boolean resolve)

name參數(shù)代表JVM需要的類的名稱,比如Foo或是java.lang.Object。

resolve參數(shù)說明類是否需要被解析。可以把類的解析理解為完全的準(zhǔn)備好執(zhí)行類。解析并不是必要的。如果JVM只需要確定該類存在或是找出其父類,則無需解析。

在java1.1版本以前,自定義ClassLoader只需要重寫loadClass方法。

defineClass方法

defineClass方法是整個(gè)ClassLoader的核心。此方法將原始字節(jié)數(shù)組轉(zhuǎn)化為一個(gè)Class對象。原始字節(jié)數(shù)組包含從本地或是遠(yuǎn)程得到的數(shù)據(jù)。

defineClass負(fù)責(zé)處理JVM的許多復(fù)雜,神秘而且依賴于具體實(shí)現(xiàn)的部分。它將字節(jié)碼解析為運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu),檢查其有效性等。不用擔(dān)心,這些你不用自己實(shí)現(xiàn)。事實(shí)上,你根本沒法重寫它,因?yàn)樵摲椒閒inal方法。

findSystemClass方法

findSysetmClass方法從本地文件系統(tǒng)中加載文件。它在本地文件系統(tǒng)中查找類文件,如果存在,使用defineClass將其從原始字節(jié)轉(zhuǎn)化為類對象。這是JVM在運(yùn)行Java應(yīng)用程序時(shí)加載類的默認(rèn)機(jī)制。

對于自定義的ClassLoader,我們只會(huì)在嘗試了別的方法來加載類內(nèi)容之后,才調(diào)用findSystemClass方法。道理很簡單:自定義的ClassLoader包含加載特殊類的一些步驟,但是并非所有的類都是特殊類。比如,即便ClassLoader需要從遠(yuǎn)程網(wǎng)站上獲取一些類,還是有許多類需要從本地的Java庫中加載。這些類并不是我們關(guān)注的重點(diǎn),因此我們需要JVM用默認(rèn)的方式來獲取。

整個(gè)流程如下:

請求自定義ClassLoader加載一個(gè)類

查看遠(yuǎn)程服務(wù)器是否有該類

如果有,則獲取并返回

如果沒有,我們假設(shè)該類是位于本地的一個(gè)基礎(chǔ)類,并調(diào)用findSystemClass從文件系統(tǒng)中加載出來。

在大多數(shù)自定義的ClassLoader中,你需要先滴啊用findSystemClass來減少對遠(yuǎn)程網(wǎng)站的訪問,因?yàn)榇蠖鄶?shù)Java類都位于本地的類庫中。但是,在下一節(jié)中你會(huì)看到,在自動(dòng)將應(yīng)用代碼編譯之前,我們不希望JVM從本地文件系統(tǒng)加載類。

resolveClass方法

如前文所說,類的加載是可以部分進(jìn)行(不進(jìn)行解析)或是徹底進(jìn)行的(進(jìn)行解析)。當(dāng)我們實(shí)現(xiàn)自己的loadClass方法時(shí),我們或許需要調(diào)用resolveClass方法,這取決于loadClass中的resolve參數(shù)的值。

findLoadedClass方法

findLoadedClass方法充當(dāng)一個(gè)緩存調(diào)用機(jī)制:當(dāng)loadClass方法被調(diào)用時(shí),他會(huì)調(diào)用這個(gè)方法來查看類是否已經(jīng)被加載過了,省去了重復(fù)加載。這個(gè)方法應(yīng)當(dāng)最先被調(diào)用。

整合一下

我們的例子中loadClass執(zhí)行以下幾步(這里我們不會(huì)特別關(guān)注到底采用了什么神奇的方法來獲取類文件。它可以是從本地,網(wǎng)絡(luò)或者是壓縮文件中獲得的,總之我們獲得了原始類文件的字節(jié)碼):

調(diào)用findLoadedClass查看是否已經(jīng)加載過該類

如果沒有,則使用神奇的魔法來獲得原始字節(jié)碼

如果獲得字節(jié)碼,調(diào)用defineClass將其轉(zhuǎn)化為Class對象

如果沒有獲得字節(jié)碼,則調(diào)用findSystemClass,看是否能從本地文件系統(tǒng)獲得類

如果resolve值為true,則調(diào)用resolveClass來解析Class對象

如果還是沒有找到類,則拋出ClassNotFoundException

否則,將類返回給調(diào)用者

CompilingClassLoader

CCL的作用是確保代碼已經(jīng)被編譯,并且是最新版本的。
以下是該類的描述:

當(dāng)需要一個(gè)類時(shí),查看該類是否在磁盤上,在當(dāng)前的目錄或是相應(yīng)的子目錄下

如果該類不存在,但是其源碼存在,在調(diào)用Java編譯器來生成類文件

如果類文件存在,查看他是否比源碼的版本舊,如果低于源碼的版本,則重新生成類文件

如果編譯失敗,或者其他的原因?qū)е聼o法從源碼中生成類文件,拋出ClassNotFoundException

如果還是沒有類文件,那么它或許在其他的一些庫中,調(diào)用findSystemClass看是否有用

如果還是找不到類,拋出ClassNotFoundException

否則,返回類

Java是如何編譯的

在深入研究之前,我們應(yīng)該回過頭來看一下Java的編譯機(jī)制??偟膩碚f,當(dāng)你請求一個(gè)類的時(shí)候,Java不只是編譯各種類信息,它還編譯了別的相關(guān)聯(lián)的類。

CCL會(huì)按需一個(gè)接一個(gè)的編譯相關(guān)的類。但是,當(dāng)CCL編譯完一個(gè)類之后試著去編譯其它相關(guān)類的時(shí)候會(huì)發(fā)現(xiàn),其它的類已經(jīng)編譯完成了。為什么呢?Java編譯器遵循一個(gè)規(guī)則:如果一個(gè)類不存在,或者它相對于源碼已經(jīng)過時(shí)了,就需要編譯它。從本質(zhì)上講,Java編譯器先CCL一步完成了大部分的工作。

CCL在編譯類的時(shí)候會(huì)打印其編譯的應(yīng)用程序。在大多數(shù)場景里面,你會(huì)看到它在程序的主類上調(diào)用編譯器。

但是,有一種情況是不會(huì)在第一次調(diào)用時(shí)編譯所有類的的。如果你通過類名Class.forNasme加載一個(gè)類,Java編譯器不知道該類需要哪些信息。在這種場景下,你會(huì)看到CCL會(huì)再次運(yùn)行Java編譯器。

如何使用CompilingClassLoader

為了使用CCL,我們需要用一種獨(dú)特的方式啟動(dòng)程序。正常的啟動(dòng)程序如下:

% java Foo arg1 arg2

而我們啟動(dòng)方式如下:

% java CCLRun Foo arg1 arg2

CCLRun是一個(gè)特殊的樁程序,它會(huì)創(chuàng)建一個(gè)CompilingClassLoader并使用它來加載程序的main方法,確保整個(gè)程序的類會(huì)通過CompilingClassLoader加載。CCLRun使用Java反射API來調(diào)用main方法并傳參

Java2中ClassLoader的變化

Java1.2以后ClassLoader有一些變動(dòng)。原有版本的ClassLoader還是兼容的,而且在新版本下開發(fā)ClassLoader更容易了

新的版本下采用了delegate模型。ClassLoader可以將類的請求委托給父類。默認(rèn)的實(shí)現(xiàn)會(huì)先調(diào)用父類的實(shí)現(xiàn),在自己加載。但是這種模式是可以改變的。所有的ClassLoader的根節(jié)點(diǎn)是系統(tǒng)ClassLoader。它默認(rèn)會(huì)從文件系統(tǒng)中加載類。

loadClass默認(rèn)實(shí)現(xiàn)

一個(gè)自定義的loadClass方法通常會(huì)嘗試用各種方法來獲得一個(gè)類的信息。如果你寫了大量的ClassLoader,你會(huì)發(fā)現(xiàn)基本上是在重復(fù)寫復(fù)雜而變化不大的代碼。

java1.2的loadClass的默認(rèn)實(shí)現(xiàn)中允許你直接重寫findClass方法,loadClass將會(huì)在合適的時(shí)候調(diào)用該方法。

這種方式的好處在于你無須重寫loadClass方法。

新方法:findClass

該方法會(huì)被loadClass的默認(rèn)實(shí)現(xiàn)調(diào)用。findClass是為了包含ClassLoader所有特定的代碼,而無需寫大量重負(fù)的其他代碼

新方法:getSystenClassLoader

無論你是否重寫了findClass或是loadClass方法,getSystemClassLoader允許你直接獲得系統(tǒng)的ClassLoader(而不是隱式的用findSystemClass獲得)

新方法:getParent

該方法允許類加載器獲取其父類加載器,從而將請求委托給它。當(dāng)你自定義的加載器無法找到類時(shí),可以使用該方法。父類加載器是指包含創(chuàng)建該類加載代碼的加載器。

源碼
// $Id$
 
import java.io.*;
 
/*
 
A CompilingClassLoader compiles your Java source on-the-fly.  It
checks for nonexistent .class files, or .class files that are older
than their corresponding source code.

*/
 
public class CompilingClassLoader extends ClassLoader
{
  // Given a filename, read the entirety of that file from disk
  // and return it as a byte array.
  private byte[] getBytes( String filename ) throws IOException {
    // Find out the length of the file
    File file = new File( filename );
    long len = file.length();
 
    // Create an array that"s just the right size for the file"s
    // contents
    byte raw[] = new byte[(int)len];
 
    // Open the file
    FileInputStream fin = new FileInputStream( file );
 
    // Read all of it into the array; if we don"t get all,
    // then it"s an error.
    int r = fin.read( raw );
    if (r != len)
      throw new IOException( "Can"t read all, "+r+" != "+len );
 
    // Don"t forget to close the file!
    fin.close();
 
    // And finally return the file contents as an array
    return raw;
  }
 
  // Spawn a process to compile the java source code file
  // specified in the "javaFile" parameter.  Return a true if
  // the compilation worked, false otherwise.
  private boolean compile( String javaFile ) throws IOException {
    // Let the user know what"s going on
    System.out.println( "CCL: Compiling "+javaFile+"..." );
 
    // Start up the compiler
    Process p = Runtime.getRuntime().exec( "javac "+javaFile );
 
    // Wait for it to finish running
    try {
      p.waitFor();
    } catch( InterruptedException ie ) { System.out.println( ie ); }
 
    // Check the return code, in case of a compilation error
    int ret = p.exitValue();
 
    // Tell whether the compilation worked
    return ret==0;
  }
 
  // The heart of the ClassLoader -- automatically compile
  // source as necessary when looking for class files
  public Class loadClass( String name, boolean resolve )
      throws ClassNotFoundException {
 
    // Our goal is to get a Class object
    Class clas = null;
 
    // First, see if we"ve already dealt with this one
    clas = findLoadedClass( name );
 
    //System.out.println( "findLoadedClass: "+clas );
 
    // Create a pathname from the class name
    // E.g. java.lang.Object => java/lang/Object
    String fileStub = name.replace( ".", "/" );
 
    // Build objects pointing to the source code (.java) and object
    // code (.class)
    String javaFilename = fileStub+".java";
    String classFilename = fileStub+".class";
 
    File javaFile = new File( javaFilename );
    File classFile = new File( classFilename );
 
    //System.out.println( "j "+javaFile.lastModified()+" c "+
    //  classFile.lastModified() );
 
    // First, see if we want to try compiling.  We do if (a) there
    // is source code, and either (b0) there is no object code,
    // or (b1) there is object code, but it"s older than the source
    if (javaFile.exists() &&
         (!classFile.exists() ||
          javaFile.lastModified() > classFile.lastModified())) {
 
      try {
        // Try to compile it.  If this doesn"t work, then
        // we must declare failure.  (It"s not good enough to use
        // and already-existing, but out-of-date, classfile)
        if (!compile( javaFilename ) || !classFile.exists()) {
          throw new ClassNotFoundException( "Compile failed: "+javaFilename );
        }
      } catch( IOException ie ) {
 
        // Another place where we might come to if we fail
        // to compile
        throw new ClassNotFoundException( ie.toString() );
      }
    }
 
    // Let"s try to load up the raw bytes, assuming they were
    // properly compiled, or didn"t need to be compiled
    try {
 
      // read the bytes
      byte raw[] = getBytes( classFilename );
 
      // try to turn them into a class
      clas = defineClass( name, raw, 0, raw.length );
    } catch( IOException ie ) {
      // This is not a failure!  If we reach here, it might
      // mean that we are dealing with a class in a library,
      // such as java.lang.Object
    }
 
    //System.out.println( "defineClass: "+clas );
 
    // Maybe the class is in a library -- try loading
    // the normal way
    if (clas==null) {
      clas = findSystemClass( name );
    }
 
    //System.out.println( "findSystemClass: "+clas );
 
    // Resolve the class, if any, but only if the "resolve"
    // flag is set to true
    if (resolve && clas != null)
      resolveClass( clas );
 
    // If we still don"t have a class, it"s an error
    if (clas == null)
      throw new ClassNotFoundException( name );
 
    // Otherwise, return the class
    return clas;
  }
}
import java.lang.reflect.*;
 
/*
 
CCLRun executes a Java program by loading it through a
CompilingClassLoader.
 
*/
 
public class CCLRun
{
  static public void main( String args[] ) throws Exception {
 
    // The first argument is the Java program (class) the user
    // wants to run
    String progClass = args[0];
 
    // And the arguments to that program are just
    // arguments 1..n, so separate those out into
    // their own array
    String progArgs[] = new String[args.length-1];
    System.arraycopy( args, 1, progArgs, 0, progArgs.length );
 
    // Create a CompilingClassLoader
    CompilingClassLoader ccl = new CompilingClassLoader();
 
    // Load the main class through our CCL
    Class clas = ccl.loadClass( progClass );
 
    // Use reflection to call its main() method, and to
    // pass the arguments in.
 
    // Get a class representing the type of the main method"s argument
    Class mainArgType[] = { (new String[0]).getClass() };
 
    // Find the standard main method in the class
    Method main = clas.getMethod( "main", mainArgType );
 
    // Create a list containing the arguments -- in this case,
    // an array of strings
    Object argsArray[] = { progArgs };
 
    // Call the method
    main.invoke( null, argsArray );
  }
}
public class Foo
{
  static public void main( String args[] ) throws Exception {
    System.out.println( "foo! "+args[0]+" "+args[1] );
    new Bar( args[0], args[1] );
  }
}
import baz.*;
 
public class Bar
{
  public Bar( String a, String b ) {
    System.out.println( "bar! "+a+" "+b );
    new Baz( a, b );
 
    try {
      Class booClass = Class.forName( "Boo" );
      Object boo = booClass.newInstance();
    } catch( Exception e ) {
      e.printStackTrace();
    }
  }
}
 
package baz;
 
public class Baz
{
  public Baz( String a, String b ) {
    System.out.println( "baz! "+a+" "+b );
  }
}
public class Boo
{
  public Boo() {
    System.out.println( "Boo!" );
  }
}


想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號(hào)!將會(huì)不定期的發(fā)放福利哦~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/76502.html

相關(guān)文章

  • 頭鷹深夜翻譯:JDK Vs. JRE Vs. JVM之間區(qū)別

    摘要:什么是為執(zhí)行字節(jié)碼提供一個(gè)運(yùn)行環(huán)境。它的實(shí)現(xiàn)主要包含三個(gè)部分,描述實(shí)現(xiàn)規(guī)格的文檔,具體實(shí)現(xiàn)和滿足要求的計(jì)算機(jī)程序以及實(shí)例具體執(zhí)行字節(jié)碼。該類先被轉(zhuǎn)化為一組字節(jié)碼并放入文件中。字節(jié)碼校驗(yàn)器通過字節(jié)碼校驗(yàn)器檢查格式并找出非法代碼。 什么是Java Development Kit (JDK)? JDK通常用來開發(fā)Java應(yīng)用和插件?;旧峡梢哉J(rèn)為是一個(gè)軟件開發(fā)環(huán)境。JDK包含Java Run...

    blair 評論0 收藏0
  • 頭鷹深夜翻譯:使用JAVA CompletableFuture20例子

    摘要:這個(gè)例子想要說明兩個(gè)事情中以為結(jié)尾的方法將會(huì)異步執(zhí)行默認(rèn)情況下即指沒有傳入的情況下,異步執(zhí)行會(huì)使用實(shí)現(xiàn),該線程池使用一個(gè)后臺(tái)線程來執(zhí)行任務(wù)。這個(gè)例子展示了如何使用一個(gè)固定大小的線程池來實(shí)現(xiàn)大寫操作。 前言 這篇博客回顧JAVA8的CompletionStageAPI以及其在JAVA庫中的標(biāo)準(zhǔn)實(shí)現(xiàn)CompletableFuture。將會(huì)通過幾個(gè)例子來展示API的各種行為。 因?yàn)镃ompl...

    AZmake 評論0 收藏0
  • 頭鷹深夜翻譯Java 2D Graphics, 簡單仿射變換

    摘要:什么是仿射變換一組設(shè)備無關(guān)的坐標(biāo)被用來將所有的坐標(biāo)信息傳遞給對象。對象作為對象狀態(tài)的一部分。類代表一個(gè)的仿射變化,將一組的坐標(biāo)進(jìn)行線性映射到另一組保留了平行關(guān)系和豎直關(guān)系的坐標(biāo)中。 什么是仿射變換 一組設(shè)備無關(guān)的坐標(biāo)被用來將所有的坐標(biāo)信息傳遞給Graphics2D對象。AffineTransform對象作為Graphics2D對象狀態(tài)的一部分。該對象定義了如何將用戶空間的坐標(biāo)轉(zhuǎn)化為設(shè)備...

    whinc 評論0 收藏0
  • 頭鷹深夜翻譯Java WeakHashMap

    摘要:本文簡介類概覽類構(gòu)造器總結(jié)類構(gòu)造方法類使用舉例類概覽是一個(gè)實(shí)現(xiàn)了接口,并且鍵為型的哈希表。中的條目不再被正常使用時(shí),會(huì)被自動(dòng)刪除。它的鍵值均支持。和絕大多數(shù)的集合類一樣,這個(gè)類不是同步的。 本文簡介 WeakHashMap類概覽 WeakHashMap類構(gòu)造器總結(jié) WeakHashMap類構(gòu)造方法 WeakHasjMap類使用舉例 1. WeakHashMap類概覽 Wea...

    BothEyes1993 評論0 收藏0
  • 頭鷹深夜翻譯:Volatile原子性, 可見性和有序性

    摘要:有可能一個(gè)線程中的動(dòng)作相對于另一個(gè)線程出現(xiàn)亂序。當(dāng)實(shí)際輸出取決于線程交錯(cuò)的結(jié)果時(shí),這種情況被稱為競爭條件。這里的問題在于代碼塊不是原子性的,而且實(shí)例的變化對別的線程不可見。這種不能同時(shí)在多個(gè)線程上執(zhí)行的部分被稱為關(guān)鍵部分。 為什么要額外寫一篇文章來研究volatile呢?是因?yàn)檫@可能是并發(fā)中最令人困惑以及最被誤解的結(jié)構(gòu)。我看過不少解釋volatile的博客,但是大多數(shù)要么不完整,要么難...

    Lionad-Morotar 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<