欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中的IO流

 更新時(shí)間:2021年08月30日 17:15:55   作者:風(fēng)吹草  
這篇文章主要介紹了java中的IO流的相關(guān)資料,需要的朋友可以參考下文

java中的IO流

前言:

在java中IO類很龐大,初學(xué)的時(shí)候覺(jué)得傻傻分不清楚。其實(shí)java流歸根結(jié)底的原理是普通字節(jié)流,字節(jié)緩沖流,轉(zhuǎn)換流。最基礎(chǔ)的是普通字節(jié)流,即從硬盤讀取字節(jié)寫入到內(nèi)存中,但在實(shí)際使用中又發(fā)現(xiàn)一些特殊的需求,所以java語(yǔ)言的設(shè)計(jì)者這引入了字節(jié)緩沖流和轉(zhuǎn)換流。所有的java IO類對(duì)IO的處理都是基于這三種流中的一種或多種;在介紹完三種流的概念之后,會(huì)對(duì)IO流的部分java類做介紹。

1.普通字節(jié)流

以FileInputStream為例子。FileInputStream的硬盤讀取方式分為兩種,一次讀取一個(gè)字節(jié)和一次讀取一個(gè)字節(jié)數(shù)組。字節(jié)數(shù)組的大小不同,實(shí)際IO耗時(shí)也不同,1為示例代碼,3展示了1代碼中讀寫耗時(shí)隨字節(jié)數(shù)組大小的變化趨勢(shì)。隨著字節(jié)數(shù)組的增大,讀寫耗時(shí)減小,主要是硬盤尋道時(shí)間(seek time)和旋轉(zhuǎn)時(shí)間(rotational latency)的減少。在硬盤讀寫耗時(shí)很長(zhǎng)時(shí),內(nèi)存讀寫的耗時(shí)相比硬盤讀寫可以忽略,硬盤讀寫的耗時(shí)分為尋道時(shí)間(seek time)、旋轉(zhuǎn)時(shí)間(rotational latency)和傳輸時(shí)間(transfer time),傳輸時(shí)間相對(duì)于尋道時(shí)間和旋轉(zhuǎn)時(shí)間(尋道時(shí)間和旋轉(zhuǎn)時(shí)間后合并稱為尋址時(shí)間)可以忽略【1】。硬盤的尋址時(shí)間在一個(gè)塊中的第一個(gè)字節(jié)耗時(shí)長(zhǎng),一個(gè)塊中的其余字節(jié)可以忽略。當(dāng)字節(jié)數(shù)組增大時(shí)(從32增加到1024*16 byte),尋址一個(gè)塊中的第一個(gè)字節(jié)的場(chǎng)景線性減少,尋址時(shí)間也線性減少,因此IO耗時(shí)呈線性減少趨勢(shì)。當(dāng)字節(jié)數(shù)組大小繼續(xù)增大(從1024 * 8增加到1024 * 1024 * 16),此時(shí)尋址時(shí)間已降到很低,相比傳輸時(shí)間可以忽略時(shí),IO耗時(shí)的變化趨于平穩(wěn)。當(dāng)字節(jié)數(shù)組大小繼續(xù)增大時(shí),讀寫耗時(shí)又出現(xiàn)增大的趨勢(shì),這個(gè)我還沒(méi)找到原因。當(dāng)在數(shù)組較大(大于1024 *1024 *4)時(shí),read(byte[])方法中除去讀寫之外也會(huì)有其它耗時(shí),測(cè)試代碼如2,測(cè)試數(shù)據(jù)如圖3附表,這個(gè)機(jī)制我還不清楚(可能需要深入了解jvm的底層實(shí)現(xiàn)了),3中在計(jì)算讀寫耗時(shí)時(shí)應(yīng)減去這部分時(shí)間。

示例代碼

public class Demo01_Copy {

 public static void main(String[] args) throws IOException {
  File src = new File ("e:\\foxit_Offline_FoxitInst.exe");
  File dest = new File("e:\\ithema\\foxit_Offline_FoxitInst.exe");

  byte[] bytes = new byte[1024*128];//調(diào)整字節(jié)數(shù)組的大小,看IO耗時(shí)的變化
  long time1 = System.currentTimeMillis();
  copyFile2(src,dest,bytes);
  long time2 = System.currentTimeMillis();
  System.out.println(time2 -time1);
 }
 
 public static void copyFile2(File src,File dest,byte[] bytes) throws IOException{
  InputStream in = new FileInputStream(src);
  OutputStream os = new FileOutputStream(dest);
  
  int len = 0;
  while((len = in.read(bytes))!=-1){
   os.write(bytes,0,len);
  }
  in.close();
  os.close();
 }
}

 1.通過(guò)FileInputStream一次讀取一個(gè)字節(jié)數(shù)組

public class Demo02_Copy {
    public static void main(String[] args) throws IOException {
        File src = new File ("e:\\1.txt");
        File dest = new File("e:\\ithema\\1.txt");

        byte[] bytes = new byte[1024*128];//調(diào)整字節(jié)數(shù)組的大小,看IO耗時(shí)的變化
        long time1 = System.currentTimeMillis();
        copyFile2(src,dest,bytes);
        long time2 = System.currentTimeMillis();
        System.out.println(time2 -time1);
    }

    public static void copyFile2(File src,File dest,byte[] bytes) throws IOException{
        InputStream in = new FileInputStream(src);
        OutputStream os = new FileOutputStream(dest);

        int len = 0;
        while((len = in.read(bytes))!=-1){
            os.write(bytes,0,len);
        }
        in.close();
        os.close();
    }
}

2.測(cè)試除硬盤內(nèi)存讀寫外的其它耗時(shí)(1.txt文件為空)

 3.當(dāng)字節(jié)數(shù)組大小變化,讀寫總耗時(shí)的變化趨勢(shì)(折線圖數(shù)據(jù)來(lái)源于表格中藍(lán)色背景填充的數(shù)據(jù))

當(dāng)數(shù)組大小從32逐漸增大到1024*16byte時(shí),IO耗時(shí)呈線性減少,這基于FileInputStream的read(byte[])實(shí)現(xiàn)。read(byte[])的源碼如4所示,read(byte b[])是一個(gè)本地方法,它保證了硬盤的尋址時(shí)間在讀取一個(gè)數(shù)組大小的字節(jié)塊的第一個(gè)字節(jié)耗時(shí)較長(zhǎng),字節(jié)塊的其余字節(jié)可以忽略。而相對(duì)于read()方法,一個(gè)字節(jié)一個(gè)字節(jié)讀取,每讀取一個(gè)字節(jié)都要重新進(jìn)行硬盤尋址。

public class FileInputStream extends InputStream
{
    public int read(byte b[]) throws IOException {
        return readBytes(b, 0, b.length);
    }
    
     /**
     * Reads a subarray as a sequence of bytes.
     * @param b the data to be written
     * @param off the start offset in the data
     * @param len the number of bytes that are written
     * @exception IOException If an I/O error has occurred.
     */
    private native int readBytes(byte b[], int off, int len) throws IOException;
}

4.FileInputStream 的 read(byte[]) 方法源碼

2.字節(jié)緩沖流

假設(shè)現(xiàn)在你要寫一個(gè)程序以計(jì)算一個(gè)text文件的行數(shù)。一種方法是使用read()方法從硬盤中一次讀取1個(gè)字節(jié)到內(nèi)存中,并檢查該字節(jié)是不是換行符“\n”【2】。這種方法已被證明是低效的。

更好的方法是使用字節(jié)緩沖流,先將字節(jié)從硬盤一次讀取一個(gè)緩沖區(qū)大小的字節(jié)到內(nèi)存中的讀緩沖區(qū),然后在從讀緩沖區(qū)中一次讀取一個(gè)字節(jié)。在逐字節(jié)讀取讀取緩沖區(qū)時(shí),檢查字節(jié)是不是換行符'\n'。字節(jié)緩沖流BufferedInputStream的源碼如5所示,先從硬盤讀取一個(gè)緩沖大小的字節(jié)塊到緩沖區(qū),然后逐個(gè)讀取緩沖區(qū)的字節(jié);當(dāng)緩沖區(qū)的字節(jié)讀取完畢后,在調(diào)用fill()方法填充緩沖區(qū)。字節(jié)緩沖流BufferedInputStream的緩沖區(qū)大小為8192。6中對(duì)比了字節(jié)緩沖流和普通字節(jié)流的讀寫效率;字節(jié)緩沖流的讀耗時(shí)僅為8ms,而沒(méi)有緩沖區(qū)的普通字節(jié)流的耗時(shí)為567ms。圖7中展示了6中字節(jié)緩沖流讀寫文件的示意圖。

public class BufferedInputStream extends FilterInputStream {
    private static int DEFAULT_BUFFER_SIZE = 8192;
    
 public synchronized int read() throws IOException {
        //當(dāng)緩沖區(qū)的字節(jié)已被讀取完畢后,調(diào)用fill()方法從硬盤讀取字節(jié)塊填充緩沖區(qū);
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        //返回緩沖區(qū)的一個(gè)字節(jié)
        return getBufIfOpen()[pos++] & 0xff;
    }

 private void fill() throws IOException {
        byte[] buffer = getBufIfOpen();
        //初始定義int markpos = -1;
        if (markpos < 0)
            pos = 0;            /* no mark: throw away the buffer */
        else if (pos >= buffer.length)  /* no room left in buffer */
            if (markpos > 0) {  /* can throw away early part of the buffer */
                int sz = pos - markpos;
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                pos = sz;
                markpos = 0;
            } else if (buffer.length >= marklimit) {
                markpos = -1;   /* buffer got too big, invalidate mark */
                pos = 0;        /* drop buffer contents */
            } else if (buffer.length >= MAX_BUFFER_SIZE) {
                throw new OutOfMemoryError("Required array size too large");
            } else {            /* grow buffer */
                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
                        pos * 2 : MAX_BUFFER_SIZE;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                    // Can't replace buf if there was an async close.
                    // Note: This would need to be changed if fill()
                    // is ever made accessible to multiple threads.
                    // But for now, the only way CAS can fail is via close.
                    // assert buf == null;
                    throw new IOException("Stream closed");
                }
                buffer = nbuf;
            }
        count = pos;
        //從硬盤讀取一個(gè)緩沖區(qū)大小的塊到緩沖區(qū)
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
            count = n + pos;
    }
}

 5.BufferedInputStream的read()方法源碼

public class Demo03_Copy {

 public static void main(String[] args) throws IOException {
  File src = new File ("e:\\settings.xml");
  File dest = new File("e:\\ithema\\settings.xml");

  byte[] bytes = new byte[1024*128];
  long time1 = System.currentTimeMillis();
  //耗時(shí):567 ms
        //copyFile1(src,dest);
  //耗時(shí):8 ms
  copyFile3(src,dest);
  long time2 = System.currentTimeMillis();
  System.out.println(time2 -time1);
 }

    //使用普通字節(jié)流
 public static void copyFile1(File src,File dest) throws IOException{
  InputStream in = new FileInputStream(src);
  OutputStream os = new FileOutputStream(dest);
  int len = 0;
  int lineSum = 1;
  while((len = in.read())!= -1){
   if(len == '\n'){
    lineSum++;
   }
   os.write(len);
  }
  System.out.println("lineSum:"+lineSum);
  in.close();
  os.close();
 }
 
    //使用字節(jié)緩沖流
 public static void copyFile3(File src,File dest) throws IOException{
  
  InputStream in = new BufferedInputStream(new FileInputStream(src));
  OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
  
  int len = 0;
  int lineSum = 1;
  while((len = in.read())!=-1){
   if(len == '\n'){
    lineSum ++;
   }
   os.write(len);
  }
  System.out.println("lineSum:"+lineSum);
  in.close();
  os.close();
 }
}

6.字節(jié)緩沖流和普通字節(jié)流的讀寫效率對(duì)比

 

 7.使用字節(jié)緩沖流在圖6中讀寫文件的示意圖

3.轉(zhuǎn)換流

轉(zhuǎn)換流實(shí)現(xiàn)了在指定的編碼方式下進(jìn)行字節(jié)編碼和字符編碼的轉(zhuǎn)換。轉(zhuǎn)換流如果直接從硬盤一次一個(gè)字節(jié)讀取的轉(zhuǎn)換流效率也很低,所以轉(zhuǎn)換流一般都是基于字節(jié)緩沖流的。轉(zhuǎn)換流InputStreamReader的使用如8所示,圖中代碼底層的執(zhí)行流程圖如9所示。InputStreamReader 的源碼解析圖如10所示,轉(zhuǎn)碼的關(guān)鍵代碼如11所示。如11,一個(gè)字符的字符編碼所占字節(jié)個(gè)數(shù)固定為2個(gè)字節(jié),但一個(gè)字符的字符編碼經(jīng)過(guò)轉(zhuǎn)換流按UTF-8格式轉(zhuǎn)換為字節(jié)編碼后,字節(jié)編碼所占字節(jié)個(gè)數(shù)為1~4個(gè)。

public class Demo01_InputStreamReader {
 public static void main(String[] args) throws IOException {
  readUTF();
 }
    
    //一次讀取一個(gè)字符
 public static void readUTF() throws IOException{
  InputStreamReader isr = new InputStreamReader(new FileInputStream("e:\\2.txt"),"UTF-8");
  int ch = 0;
  while((ch = isr.read())!=-1){
   System.out.println((char)ch);
  }
  isr.close();
 }
}

8. 使用轉(zhuǎn)換流InputStreamReader一次讀取一個(gè)字符

 

9 .InputStreamReader在read()時(shí)的底層流程圖(文件中的字節(jié)編碼可通過(guò)FileInputStream讀取查看)

 

10 .InputStreamReader的read()源碼解析圖

class UTF_8 extends Unicode{
    private CoderResult decodeArrayLoop(ByteBuffer paramByteBuffer, CharBuffer paramCharBuffer)
    {
      byte[] arrayOfByte = paramByteBuffer.array();
      int i = paramByteBuffer.arrayOffset() + paramByteBuffer.position();
      int j = paramByteBuffer.arrayOffset() + paramByteBuffer.limit();
      char[] arrayOfChar = paramCharBuffer.array();
      int k = paramCharBuffer.arrayOffset() + paramCharBuffer.position();
      int m = paramCharBuffer.arrayOffset() + paramCharBuffer.limit();
      int n = k + Math.min(j - i, m - k);
      while ((k < n) && (arrayOfByte[i] >= 0))
        arrayOfChar[(k++)] = (char)arrayOfByte[(i++)];
      while (i < j)
      {
        int i1 = arrayOfByte[i];
        if (i1 >= 0)
        {
          if (k >= m)
            return xflow(paramByteBuffer, i, j, paramCharBuffer, k, 1);
          arrayOfChar[(k++)] = (char)i1;
          i++;
        }
        else
        {
          int i2;
          if ((i1 >> 5 == -2) && ((i1 & 0x1E) != 0))
          {
            if ((j - i < 2) || (k >= m))
              return xflow(paramByteBuffer, i, j, paramCharBuffer, k, 2);
            i2 = arrayOfByte[(i + 1)];
            if (isNotContinuation(i2))
              return malformedForLength(paramByteBuffer, i, paramCharBuffer, k, 1);
            arrayOfChar[(k++)] = (char)(i1 << 6 ^ i2 ^ 0xF80);
            i += 2;
          }
          else
          {
            int i3;
            int i4;
            if (i1 >> 4 == -2)
            {
              i2 = j - i;
              if ((i2 < 3) || (k >= m))
              {
                if ((i2 > 1) && (isMalformed3_2(i1, arrayOfByte[(i + 1)])))
                  return malformedForLength(paramByteBuffer, i, paramCharBuffer, k, 1);
                return xflow(paramByteBuffer, i, j, paramCharBuffer, k, 3);
              }
              i3 = arrayOfByte[(i + 1)];
              i4 = arrayOfByte[(i + 2)];
              if (isMalformed3(i1, i3, i4))
                return malformed(paramByteBuffer, i, paramCharBuffer, k, 3);
              char c = (char)(i1 << 12 ^ i3 << 6 ^ (i4 ^ 0xFFFE1F80));
              if (Character.isSurrogate(c))
                return malformedForLength(paramByteBuffer, i, paramCharBuffer, k, 3);
              arrayOfChar[(k++)] = c;
              i += 3;
            }
            else if (i1 >> 3 == -2)
            {
              i2 = j - i;
              if ((i2 < 4) || (m - k < 2))
              {
                i1 &= 255;
                if ((i1 > 244) || ((i2 > 1) && (isMalformed4_2(i1, arrayOfByte[(i + 1)] & 0xFF))))
                  return malformedForLength(paramByteBuffer, i, paramCharBuffer, k, 1);
                if ((i2 > 2) && (isMalformed4_3(arrayOfByte[(i + 2)])))
                  return malformedForLength(paramByteBuffer, i, paramCharBuffer, k, 2);
                return xflow(paramByteBuffer, i, j, paramCharBuffer, k, 4);
              }
              i3 = arrayOfByte[(i + 1)];
              i4 = arrayOfByte[(i + 2)];
              int i5 = arrayOfByte[(i + 3)];
              int i6 = i1 << 18 ^ i3 << 12 ^ i4 << 6 ^ (i5 ^ 0x381F80);
              if ((isMalformed4(i3, i4, i5)) || (!Character.isSupplementaryCodePoint(i6)))
                return malformed(paramByteBuffer, i, paramCharBuffer, k, 4);
              arrayOfChar[(k++)] = Character.highSurrogate(i6);
              arrayOfChar[(k++)] = Character.lowSurrogate(i6);
              i += 4;
            }
            else
            {
              return malformed(paramByteBuffer, i, paramCharBuffer, k, 1);
            }
          }
        }
      }
      return xflow(paramByteBuffer, i, j, paramCharBuffer, k, 0);
    }
}

11 .UTF_8中將字節(jié)編碼解碼為字符編碼的方法decodeArrayLoop()

4.常用的IO類FileReader和BufferedReader

FileReader(String fileName)和InputStreamReader(new FileInputStream(String fileName))是等價(jià)的,如12所示,具體實(shí)現(xiàn)參見(jiàn)第3節(jié)。BufferedReader的實(shí)現(xiàn)與FileReader不同,它們的性能對(duì)比如13所示。14展示了BufferedReader的使用,這為了和7中InputStreamReader(new FileInputStream(String fileName))的使用做對(duì)比。14中代碼底層的執(zhí)行流程圖如15所示。BufferedReader的方法read()的源碼解析如16所示。BufferedReader和FileReader在字符編碼和字節(jié)編碼的轉(zhuǎn)換時(shí)都調(diào)用了CharsetDecoder.decode()方法;不同的是BufferedReader一次轉(zhuǎn)換了8192個(gè)字符(15),而FileReader一次只轉(zhuǎn)換了2個(gè)字符(9)。但由于BufferedReader和FileReader的字節(jié)緩沖區(qū)大小于均為8192個(gè)字節(jié),因此BufferedReader與FileReader效率相差不大。

public class FileReader extends InputStreamReader {
    public FileReader(String fileName) throws FileNotFoundException {
        super(new FileInputStream(fileName));
    }
}

12.FileReader(String filePath)的構(gòu)造方法

public class Demo01_Copy {

 public static void main(String[] args) throws IOException {
  File src = new File ("e:\\foxit_Offline_FoxitInst.exe");
  File dest = new File("e:\\ithema\\foxit_Offline_FoxitInst.exe");

  long time1 = System.currentTimeMillis();
        //耗時(shí):3801 ms
  //copyFile5(src,dest,bytes);
  //耗時(shí):2938 ms
  copyFile6(src,dest);
  long time2 = System.currentTimeMillis();
  System.out.println(time2 -time1);
 }


 public static void copyFile5(File src ,File dest) throws IOException {
  FileReader fr = new FileReader(src);
  FileWriter fw = new FileWriter(dest);
  int len = 0;
  while((len=fr.read())!=-1){
   fw.write(len);
  }
  fr.close();
  fw.close();
 }

 public static void copyFile6(File src,File dest) throws IOException{
  BufferedReader br = new BufferedReader(new FileReader(src));
  BufferedWriter bw = new BufferedWriter(new FileWriter(dest));
  int len = 0;
  while((len=br.read())!=-1){
   bw.write(len);
  }
  br.close();
  bw.close();
 }
}

13.FileReader和BufferedReader的性能對(duì)比

public class Demo01_BufferedReader {
 public static void main(String[] args) throws IOException {
  readUTF();
 }
    
    //一次讀取一個(gè)字符
 public static void readUTF() throws IOException{
  BufferedReader br = new BufferedReader(
            new InputStreamReader(new FileInputStream("e:\\2.txt"),"UTF-8"));
  int ch = 0;
  while((ch = br.read())!=-1){
   System.out.println((char)ch);
  }
  br.close();
 }
}

14.使用BufferedReader一次讀取一個(gè)字符(與圖7做對(duì)比)

 

15.BufferedReader在read()時(shí)的底層流程圖(與圖8做對(duì)比)

 

16.BufferedReader的read()源碼解析圖(與圖9做對(duì)比)

5.總結(jié)

普通字節(jié)流是基礎(chǔ),是最簡(jiǎn)單高效的流。如果沒(méi)有特殊的需求,只是高效的進(jìn)行文件讀寫,選擇合適的字節(jié)數(shù)組大小,一次從硬盤讀取一個(gè)字節(jié)數(shù)組大小的字節(jié)塊,其效率是最高的。

字節(jié)緩沖流是為行數(shù)統(tǒng)計(jì),按行讀取等特殊需求而設(shè)計(jì)的。相比于直接從硬盤一次讀取一個(gè)字節(jié);先從硬盤一次讀取一個(gè)緩沖區(qū)大小的字節(jié)塊到緩沖區(qū)(位于內(nèi)存),再?gòu)木彌_區(qū)一個(gè)字節(jié)一個(gè)字節(jié)的讀取并判斷是不是行末尾('\n')的效率更高。

轉(zhuǎn)換流實(shí)現(xiàn)了在指定的編碼方式下進(jìn)行字節(jié)編碼和字符編碼的轉(zhuǎn)換。轉(zhuǎn)換流如果直接從硬盤一次一個(gè)字節(jié)讀取的轉(zhuǎn)換流效率也很低,所以轉(zhuǎn)換流一般都是基于字節(jié)緩沖流的。

以上就是java中的IO流的詳細(xì)內(nèi)容,更多關(guān)于java中的IO流的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!,希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis創(chuàng)建項(xiàng)目報(bào)Invalid?bound?statement?(not?found)錯(cuò)誤解決方法

    mybatis創(chuàng)建項(xiàng)目報(bào)Invalid?bound?statement?(not?found)錯(cuò)誤解決方法

    使用MyBatis能夠幫助我們將SQL語(yǔ)句和Java代碼分離,這篇文章主要給大家介紹了關(guān)于mybatis創(chuàng)建項(xiàng)目報(bào)Invalid?bound?statement?(not?found)錯(cuò)誤的解決方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼

    SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼

    H2數(shù)據(jù)庫(kù)是一個(gè)開源的關(guān)系型數(shù)據(jù)庫(kù),本文重點(diǎn)給大家介紹SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • 解析Java多線程之常見(jiàn)鎖策略與CAS中的ABA問(wèn)題

    解析Java多線程之常見(jiàn)鎖策略與CAS中的ABA問(wèn)題

    本篇文章介紹了常見(jiàn)的鎖策略,并說(shuō)明了synchronized關(guān)鍵字加的鎖類型不是單一一種鎖類型的,根據(jù)可重入鎖與非可重入鎖引出了死鎖的概念與死鎖條件,最后介紹了CAS指令以及CAS鎖產(chǎn)生的ABA問(wèn)題及其解決方案,需要的朋友可以參考下
    2022-06-06
  • Linux下JDK安裝教程

    Linux下JDK安裝教程

    這篇文章主要為大家詳細(xì)介紹了Linux下JDK安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • logback.xml動(dòng)態(tài)配置程序路徑的操作

    logback.xml動(dòng)態(tài)配置程序路徑的操作

    這篇文章主要介紹了logback.xml動(dòng)態(tài)配置程序路徑的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議

    Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議

    這篇文章主要介紹了Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議的相關(guān)資料,非常具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-05-05
  • 深入了解Java核心類庫(kù)--Date,Calendar,DateFormat類

    深入了解Java核心類庫(kù)--Date,Calendar,DateFormat類

    這篇文章主要為大家詳細(xì)介紹了javaDate,Calendar,DateFormat類定義與使用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助
    2021-07-07
  • SpringBoot分布式文件存儲(chǔ)數(shù)據(jù)庫(kù)mongod

    SpringBoot分布式文件存儲(chǔ)數(shù)據(jù)庫(kù)mongod

    MongoDB是一個(gè)基于分布式文件存儲(chǔ)的NoSQL數(shù)據(jù)庫(kù),由C++語(yǔ)言編寫,旨在為Web應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。MongoDB是一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫(kù)中功能最豐富最像關(guān)系數(shù)據(jù)庫(kù)的
    2023-02-02
  • jar包雙擊執(zhí)行程序的方法

    jar包雙擊執(zhí)行程序的方法

    這篇文章主要介紹了jar包雙擊執(zhí)行程序的方法,可實(shí)現(xiàn)雙擊jar包直接執(zhí)行Java程序的功能,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • Spring boot配置文件加解密詳解

    Spring boot配置文件加解密詳解

    這篇文章主要給大家介紹了關(guān)于Spring boot配置文件加解密的相關(guān)資料,文中通過(guò)示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03

最新評(píng)論