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

PipedWriter和PipedReader源碼分析_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

 更新時(shí)間:2017年05月22日 11:32:26   投稿:mrr  
這篇文章主要介紹了PipedWriter和PipedReader源碼分析_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下

PipedWriter和PipedReader源碼分析

1. PipedWriter 源碼(基于jdk1.7.40) 

package java.io;
 public class PipedWriter extends Writer {
   // 與PipedWriter通信的PipedReader對(duì)象
   private PipedReader sink;
   // PipedWriter的關(guān)閉標(biāo)記
   private boolean closed = false;
   // 構(gòu)造函數(shù),指定配對(duì)的PipedReader
   public PipedWriter(PipedReader snk) throws IOException {
     connect(snk);
   }
   // 構(gòu)造函數(shù)
   public PipedWriter() {
   }
   // 將“PipedWriter” 和 “PipedReader”連接。
   public synchronized void connect(PipedReader snk) throws IOException {
     if (snk == null) {
       throw new NullPointerException();
     } else if (sink != null || snk.connected) {
       throw new IOException("Already connected");
     } else if (snk.closedByReader || closed) {
       throw new IOException("Pipe closed");
     }
     sink = snk;
     snk.in = -1;
     snk.out = 0;
     // 設(shè)置“PipedReader”和“PipedWriter”為已連接狀態(tài)
     // connected是PipedReader中定義的,用于表示“PipedReader和PipedWriter”是否已經(jīng)連接
     snk.connected = true;
   }
   // 將一個(gè)字符c寫(xiě)入“PipedWriter”中。
   // 將c寫(xiě)入“PipedWriter”之后,它會(huì)將c傳輸給“PipedReader”
   public void write(int c) throws IOException {
     if (sink == null) {
       throw new IOException("Pipe not connected");
     }
     sink.receive(c);
   }
   // 將字符數(shù)組b寫(xiě)入“PipedWriter”中。
   // 將數(shù)組b寫(xiě)入“PipedWriter”之后,它會(huì)將其傳輸給“PipedReader”
   public void write(char cbuf[], int off, int len) throws IOException {
     if (sink == null) {
       throw new IOException("Pipe not connected");
     } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < ) {
       throw new IndexOutOfBoundsException();
     }
     sink.receive(cbuf, off, len);
   }
   // 清空“PipedWriter”。
   // 這里會(huì)調(diào)用“PipedReader”的notifyAll();
   // 目的是讓“PipedReader”放棄對(duì)當(dāng)前資源的占有,讓其它的等待線程(等待讀取PipedWriter的線程)讀取“PipedWriter”的值。
   public synchronized void flush() throws IOException {
     if (sink != null) {
       if (sink.closedByReader || closed) {
         throw new IOException("Pipe closed");
       }
       synchronized (sink) {
         sink.notifyAll();
       }
     }
   }
   // 關(guān)閉“PipedWriter”。
   // 關(guān)閉之后,會(huì)調(diào)用receivedLast()通知“PipedReader”它已經(jīng)關(guān)閉。
   public void close() throws IOException {
     closed = true;
     if (sink != null) {
       sink.receivedLast();
     }
   }
 }

2. PipedReader 源碼(基于jdk1.7.40)    

package java.io;
  public class PipedReader extends Reader {
    // “PipedWriter”是否關(guān)閉的標(biāo)記
    boolean closedByWriter = false;
    // “PipedReader”是否關(guān)閉的標(biāo)記
    boolean closedByReader = false;
    // “PipedReader”與“PipedWriter”是否連接的標(biāo)記
    // 它在PipedWriter的connect()連接函數(shù)中被設(shè)置為true
   boolean connected = false;
   Thread readSide;  // 讀取“管道”數(shù)據(jù)的線程
   Thread writeSide;  // 向“管道”寫(xiě)入數(shù)據(jù)的線程
   // “管道”的默認(rèn)大小
  private static final int DEFAULT_PIPE_SIZE = 1024;
   // 緩沖區(qū)
   char buffer[];
   //下一個(gè)寫(xiě)入字符的位置。in==out代表滿,說(shuō)明“寫(xiě)入的數(shù)據(jù)”全部被讀取了。
   int in = -;
   //下一個(gè)讀取字符的位置。in==out代表滿,說(shuō)明“寫(xiě)入的數(shù)據(jù)”全部被讀取了。
   int out = ;
   // 構(gòu)造函數(shù):指定與“PipedReader”關(guān)聯(lián)的“PipedWriter”
   public PipedReader(PipedWriter src) throws IOException {
     this(src, DEFAULT_PIPE_SIZE);
   }
   // 構(gòu)造函數(shù):指定與“PipedReader”關(guān)聯(lián)的“PipedWriter”,以及“緩沖區(qū)大小”
   public PipedReader(PipedWriter src, int pipeSize) throws IOException {
     initPipe(pipeSize);
     connect(src);
   }
   // 構(gòu)造函數(shù):默認(rèn)緩沖區(qū)大小是1024字符
   public PipedReader() {
     initPipe(DEFAULT_PIPE_SIZE);
   }
   // 構(gòu)造函數(shù):指定緩沖區(qū)大小是pipeSize
   public PipedReader(int pipeSize) {
     initPipe(pipeSize);
   }
   // 初始化“管道”:新建緩沖區(qū)大小
   private void initPipe(int pipeSize) {
    if (pipeSize <= 0) {
       throw new IllegalArgumentException("Pipe size <= 0");
     }
     buffer = new char[pipeSize];
   }
   // 將“PipedReader”和“PipedWriter”綁定。
   // 實(shí)際上,這里調(diào)用的是PipedWriter的connect()函數(shù)
   public void connect(PipedWriter src) throws IOException {
     src.connect(this);
   }
   // 接收int類型的數(shù)據(jù)b。
   // 它只會(huì)在PipedWriter的write(int b)中會(huì)被調(diào)用
   synchronized void receive(int c) throws IOException {
     // 檢查管道狀態(tài)
     if (!connected) {
       throw new IOException("Pipe not connected");
     } else if (closedByWriter || closedByReader) {
       throw new IOException("Pipe closed");
     } else if (readSide != null && !readSide.isAlive()) {
       throw new IOException("Read end dead");
     }
     // 獲取“寫(xiě)入管道”的線程
     writeSide = Thread.currentThread();
     // 如果“管道中被讀取的數(shù)據(jù),等于寫(xiě)入管道的數(shù)據(jù)”時(shí),
    // 則每隔1000ms檢查“管道狀態(tài)”,并喚醒管道操作:若有“讀取管道數(shù)據(jù)線程被阻塞”,則喚醒該線程。
     while (in == out) {
       if ((readSide != null) && !readSide.isAlive()) {
         throw new IOException("Pipe broken");
       }
       /* full: kick any waiting readers */
       notifyAll();
       try {
        wait(1000);
       } catch (InterruptedException ex) {
         throw new java.io.InterruptedIOException();
       }
     }
    if (in < 0) {
     in = 0;
      out = 0;
     }
     buffer[in++] = (char) c;
     if (in >= buffer.length) {
      in = 0;
     }
   }
   // 接收字符數(shù)組b。
   synchronized void receive(char c[], int off, int len) throws IOException {
     while (--len >= ) {
      receive(c[off++]);
     }
   }
   // 當(dāng)PipedWriter被關(guān)閉時(shí),被調(diào)用
   synchronized void receivedLast() {
     closedByWriter = true;
     notifyAll();
   }
   // 從管道(的緩沖)中讀取一個(gè)字符,并將其轉(zhuǎn)換成int類型
   public synchronized int read() throws IOException {
     if (!connected) {
       throw new IOException("Pipe not connected");
     } else if (closedByReader) {
       throw new IOException("Pipe closed");
     } else if (writeSide != null && !writeSide.isAlive()
          && !closedByWriter && (in < )) {
       throw new IOException("Write end dead");
     }
     readSide = Thread.currentThread();
    int trials = 2;
    while (in < 0) {
       if (closedByWriter) {
         /* closed by writer, return EOF */
         return -1;
       }
       if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < )) {
         throw new IOException("Pipe broken");
       }
       /* might be a writer waiting */
       notifyAll();
       try {
        wait(1000);
       } catch (InterruptedException ex) {
         throw new java.io.InterruptedIOException();
       }
     }
     int ret = buffer[out++];
     if (out >= buffer.length) {
      out = 0;
     }
     if (in == out) {
       /* now empty */
      in = -1;
     }
     return ret;
   }
   // 從管道(的緩沖)中讀取數(shù)據(jù),并將其存入到數(shù)組b中
   public synchronized int read(char cbuf[], int off, int len) throws IOException {
     if (!connected) {
       throw new IOException("Pipe not connected");
     } else if (closedByReader) {
       throw new IOException("Pipe closed");
     } else if (writeSide != null && !writeSide.isAlive()
         && !closedByWriter && (in < 0)) {
       throw new IOException("Write end dead");
     }
    if ((off < 0) || (off > cbuf.length) || (len < 0) ||
      ((off + len) > cbuf.length) || ((off + len) < 0)) {
       throw new IndexOutOfBoundsException();
     } else if (len == 0) {
      return 0;
     }
     /* possibly wait on the first character */
     int c = read();
    if (c < 0) {
      return -1;
     }
     cbuf[off] = (char)c;
    int rlen = 1;
    while ((in >= 0) && (--len > 0)) {
       cbuf[off + rlen] = buffer[out++];
       rlen++;
       if (out >= buffer.length) {
       out = 0;
       }
       if (in == out) {
         /* now empty */
         in = -;
       }
     }
     return rlen;
   }
   // 是否能從管道中讀取下一個(gè)數(shù)據(jù)
   public synchronized boolean ready() throws IOException {
     if (!connected) {
       throw new IOException("Pipe not connected");
     } else if (closedByReader) {
       throw new IOException("Pipe closed");
     } else if (writeSide != null && !writeSide.isAlive()
          && !closedByWriter && (in < )) {
       throw new IOException("Write end dead");
     }
    if (in < 0) {
       return false;
     } else {
       return true;
     }
   }
   // 關(guān)閉PipedReader
   public void close() throws IOException {
     in = -;
     closedByReader = true;
   }
 }

示例

下面,我們看看多線程中通過(guò)PipedWriter和PipedReader通信的例子。例子中包括3個(gè)類:Receiver.java, Sender.java 和 PipeTest.java

Receiver.java的代碼如下:  

 import java.io.IOException;  
 import java.io.PipedReader;  
 @SuppressWarnings("all")  
 /** 
  * 接收者線程 
  */  
 public class Receiver extends Thread {  
   // 管道輸入流對(duì)象。
   // 它和“管道輸出流(PipedWriter)”對(duì)象綁定,
   // 從而可以接收“管道輸出流”的數(shù)據(jù),再讓用戶讀取。
   private PipedReader in = new PipedReader();  
   // 獲得“管道輸入流對(duì)象”
   public PipedReader getReader(){  
     return in;  
   }  
   @Override
   public void run(){  
     readMessageOnce() ;
     //readMessageContinued() ;
   }
   // 從“管道輸入流”中讀取次數(shù)據(jù)
   public void readMessageOnce(){  
     // 雖然buf的大小是2048個(gè)字符,但最多只會(huì)從“管道輸入流”中讀取1024個(gè)字符。
    // 因?yàn)椋肮艿垒斎肓鳌钡木彌_區(qū)大小默認(rèn)只有1024個(gè)字符。
     char[] buf = new char[2048];  
     try {  
       int len = in.read(buf);  
      System.out.println(new String(buf,0,len));  
       in.close();  
     } catch (IOException e) {  
       e.printStackTrace();  
     }  
   }
   // 從“管道輸入流”讀取>1024個(gè)字符時(shí),就停止讀取
  public void readMessageContinued(){
    int total=0;
     while(true) {
       char[] buf = new char[];
       try {
         int len = in.read(buf);
         total += len;
         System.out.println(new String(buf,,len));
        // 若讀取的字符總數(shù)>1024,則退出循環(huán)。
       if (total > 1024)
           break;
       } catch (IOException e) {
         e.printStackTrace();
       }
     }
     try {
       in.close(); 
     } catch (IOException e) {  
       e.printStackTrace();  
     }  
   }  
 }
 
Sender.java的代碼如下:
 
 import java.io.IOException;  
  import java.io.PipedWriter;  
 @SuppressWarnings("all")
 /** 
  * 發(fā)送者線程 
  */  
 public class Sender extends Thread {  
   // 管道輸出流對(duì)象。
   // 它和“管道輸入流(PipedReader)”對(duì)象綁定,
   // 從而可以將數(shù)據(jù)發(fā)送給“管道輸入流”的數(shù)據(jù),然后用戶可以從“管道輸入流”讀取數(shù)據(jù)。
   private PipedWriter out = new PipedWriter();
   // 獲得“管道輸出流”對(duì)象
   public PipedWriter getWriter(){
     return out;
   }  
   @Override
   public void run(){  
     writeShortMessage();
     //writeLongMessage();
   }  
   // 向“管道輸出流”中寫(xiě)入一則較簡(jiǎn)短的消息:"this is a short message" 
   private void writeShortMessage() {
     String strInfo = "this is a short message" ;
     try {
       out.write(strInfo.toCharArray());
       out.close();  
     } catch (IOException e) {  
       e.printStackTrace();  
     }  
   }
   // 向“管道輸出流”中寫(xiě)入一則較長(zhǎng)的消息
   private void writeLongMessage() {
     StringBuilder sb = new StringBuilder();
    // 通過(guò)for循環(huán)寫(xiě)入1020個(gè)字符
     for (int i=0; i<102; i++)
      sb.append("0123456789");
    // 再寫(xiě)入26個(gè)字符。
    sb.append("abcdefghijklmnopqrstuvwxyz");
    // str的總長(zhǎng)度是1020+26=1046個(gè)字符
    String str = sb.toString();
    try {
      // 將1046個(gè)字符寫(xiě)入到“管道輸出流”中
       out.write(str);
       out.close();
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }
 

PipeTest.java的代碼如下: 

 import java.io.PipedReader;
 import java.io.PipedWriter;
 import java.io.IOException;
 @SuppressWarnings("all")  
 /** 
  * 管道輸入流和管道輸出流的交互程序
  */  
 public class PipeTest {  
   public static void main(String[] args) {  
    Sender t1 = new Sender();  
   Receiver t2 = new Receiver();  
    PipedWriter out = t1.getWriter();  
     PipedReader in = t2.getReader();  
     try {  
       //管道連接。下面句話的本質(zhì)是一樣。
       //out.connect(in);  
       in.connect(out);  
       /** 
       * Thread類的START方法: 
       * 使該線程開(kāi)始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法。  
       * 結(jié)果是兩個(gè)線程并發(fā)地運(yùn)行;當(dāng)前線程(從調(diào)用返回給 start 方法)和另一個(gè)線程(執(zhí)行其 run 方法)。  
       * 多次啟動(dòng)一個(gè)線程是非法的。特別是當(dāng)線程已經(jīng)結(jié)束執(zhí)行后,不能再重新啟動(dòng)。  
       */
       t.start();
       t.start();
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

運(yùn)行結(jié)果:

this is a short message

結(jié)果說(shuō)明:

(01) in.connect(out);

        它的作用是將“管道輸入流”和“管道輸出流”關(guān)聯(lián)起來(lái)。查看PipedWriter.java和PipedReader.java中connect()的源碼;我們知道 out.connect(in); 等價(jià)于 in.connect(out);

(02)

t1.start(); // 啟動(dòng)“Sender”線程
t2.start(); // 啟動(dòng)“Receiver”線程

先查看Sender.java的源碼,線程啟動(dòng)后執(zhí)行run()函數(shù);在Sender.java的run()中,調(diào)用writeShortMessage();

writeShortMessage();的作用就是向“管道輸出流”中寫(xiě)入數(shù)據(jù)"this is a short message" ;這條數(shù)據(jù)會(huì)被“管道輸入流”接收到。下面看看這是如何實(shí)現(xiàn)的。

先看write(char char的源碼。PipedWriter.java繼承于Writer.java;Writer.java中write(char c[])的源碼如下:

public void write(char cbuf[]) throws IOException {
  write(cbuf, 0, cbuf.length);
}

實(shí)際上write(char c[])是調(diào)用的PipedWriter.java中的write(char c[], int off, int len)函數(shù)。查看write(char c[], int off, int len)的源碼,我們發(fā)現(xiàn):它會(huì)調(diào)用 sink.receive(cbuf, off, len); 進(jìn)一步查看receive(char c[], int off, int len)的定義,我們知道sink.receive(cbuf, off, len)的作用就是:將“管道輸出流”中的數(shù)據(jù)保存到“管道輸入流”的緩沖中。而“管道輸入流”的緩沖區(qū)buffer的默認(rèn)大小是1024個(gè)字符。

至此,我們知道:t1.start()啟動(dòng)Sender線程,而Sender線程會(huì)將數(shù)據(jù)"this is a short message"寫(xiě)入到“管道輸出流”;而“管道輸出流”又會(huì)將該數(shù)據(jù)傳輸給“管道輸入流”,即而保存在“管道輸入流”的緩沖中。

接下來(lái),我們看看“用戶如何從‘管道輸入流'的緩沖中讀取數(shù)據(jù)”。這實(shí)際上就是Receiver線程的動(dòng)作。

t2.start() 會(huì)啟動(dòng)Receiver線程,從而執(zhí)行Receiver.java的run()函數(shù)。查看Receiver.java的源碼,我們知道run()調(diào)用了readMessageOnce()。

而readMessageOnce()就是調(diào)用in.read(buf)從“管道輸入流in”中讀取數(shù)據(jù),并保存到buf中。

通過(guò)上面的分析,我們已經(jīng)知道“管道輸入流in”的緩沖中的數(shù)據(jù)是"this is a short message";因此,buf的數(shù)據(jù)就是"this is a short message"。

為了加深對(duì)管道的理解。我們接著進(jìn)行下面兩個(gè)小試驗(yàn)。

試驗(yàn)一:修改Sender.java

public void run(){  
  writeShortMessage();
  //writeLongMessage();
}

修改為

public void run(){  
  //writeShortMessage();
  writeLongMessage();
}

運(yùn)行程序。運(yùn)行結(jié)果如下: 

從中,我們看出,程序運(yùn)行出錯(cuò)!拋出異常 java.io.IOException: Pipe closed

為什么會(huì)這樣呢?

我分析一下程序流程。

(01) 在PipeTest中,通過(guò)in.connect(out)將輸入和輸出管道連接起來(lái);然后,啟動(dòng)兩個(gè)線程。t1.start()啟動(dòng)了線程Sender,t2.start()啟動(dòng)了線程Receiver。

(02) Sender線程啟動(dòng)后,通過(guò)writeLongMessage()寫(xiě)入數(shù)據(jù)到“輸出管道”,out.write(str.toCharArray())共寫(xiě)入了1046個(gè)字符。而根據(jù)PipedWriter的源碼,PipedWriter的write()函數(shù)會(huì)調(diào)用PipedReader的receive()函數(shù)。而觀察PipedReader的receive()函數(shù),我們知道,PipedReader會(huì)將接受的數(shù)據(jù)存儲(chǔ)緩沖區(qū)。仔細(xì)觀察receive()函數(shù),有如下代碼:

while (in == out) {
  if ((readSide != null) && !readSide.isAlive()) {
    throw new IOException("Pipe broken");
  }
  /* full: kick any waiting readers */
  notifyAll();
  try {
    wait(1000);
  } catch (InterruptedException ex) {
    throw new java.io.InterruptedIOException();
  }
}

而in和out的初始值分別是in=-1, out=0;結(jié)合上面的while(in==out)。我們知道,它的含義就是,每往管道中寫(xiě)入一個(gè)字符,就達(dá)到了in==out這個(gè)條件。然后,就調(diào)用notifyAll(),喚醒“讀取管道的線程”。
也就是,每往管道中寫(xiě)入一個(gè)字符,都會(huì)阻塞式的等待其它線程讀取。

然而,PipedReader的緩沖區(qū)的默認(rèn)大小是1024!但是,此時(shí)要寫(xiě)入的數(shù)據(jù)卻有1046!所以,一次性最多只能寫(xiě)入1024個(gè)字符。

(03) Receiver線程啟動(dòng)后,會(huì)調(diào)用readMessageOnce()讀取管道輸入流。讀取1024個(gè)字符會(huì),會(huì)調(diào)用close()關(guān)閉,管道。

由(02)和(03)的分析可知,Sender要往管道寫(xiě)入1046個(gè)字符。其中,前1024個(gè)字符(緩沖區(qū)容量是1024)能正常寫(xiě)入,并且每寫(xiě)入一個(gè)就讀取一個(gè)。當(dāng)寫(xiě)入1025個(gè)字符時(shí),依然是依次的調(diào)用PipedWriter.java中的write();然后,write()中調(diào)用PipedReader.java中的receive();在PipedReader.java中,最終又會(huì)調(diào)用到receive(int c)函數(shù)。 而此時(shí),管道輸入流已經(jīng)被關(guān)閉,也就是closedByReader為true,所以拋出throw new IOException("Pipe closed")。
我們對(duì)“試驗(yàn)一”繼續(xù)進(jìn)行修改,解決該問(wèn)題。

試驗(yàn)二: 在“試驗(yàn)一”的基礎(chǔ)上繼續(xù)修改Receiver.java

public void run(){  
  readMessageOnce() ;
  //readMessageContinued() ;
}

修改為

public void run(){  
  //readMessageOnce() ;
  readMessageContinued() ;
}

此時(shí),程序能正常運(yùn)行。運(yùn)行結(jié)果為:

01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789abcd
efghijklmnopqrstuvwxyz

以上所述是小編給大家介紹的PipedWriter和PipedReader源碼分析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Java創(chuàng)建對(duì)象的幾種方法

    Java創(chuàng)建對(duì)象的幾種方法

    這篇文章主要為大家詳細(xì)介紹了Java創(chuàng)建對(duì)象的幾種方法,使用new創(chuàng)建、使用object.clone()創(chuàng)建、使用反序列化創(chuàng)建等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • SpringBoot下使用MyBatis-Puls代碼生成器的方法

    SpringBoot下使用MyBatis-Puls代碼生成器的方法

    這篇文章主要介紹了SpringBoot下使用MyBatis-Puls代碼生成器的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 完美解決Logback configuration error detected的問(wèn)題

    完美解決Logback configuration error detected的問(wèn)題

    這篇文章主要介紹了完美解決Logback configuration error detected的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 關(guān)于mybatis-plus邏輯刪除無(wú)效的問(wèn)題

    關(guān)于mybatis-plus邏輯刪除無(wú)效的問(wèn)題

    這篇文章主要介紹了mybatis-plus邏輯刪除無(wú)效,文中給大家提到了配置過(guò)程及全部代碼,代碼簡(jiǎn)單易懂,需要的朋友可以參考下
    2021-09-09
  • Java中String類的常用方法總結(jié)

    Java中String類的常用方法總結(jié)

    java.lang.String?類代表字符串。Java程序中所有的字符串文字(例如"abc"?)都可以被看作是實(shí)現(xiàn)此類的實(shí)例。本文主要為大家介紹了String類的常用方法,需要的可以參考一下
    2022-11-11
  • Spring Boot 配置 IDEA和DevTools 熱部署的方法

    Spring Boot 配置 IDEA和DevTools 熱部署的方法

    這篇文章主要介紹了Spring Boot 配置 IDEA和DevTools 熱部署的方法,需要的朋友可以參考下
    2018-02-02
  • Java中工具Jstack的使用實(shí)例

    Java中工具Jstack的使用實(shí)例

    jstack用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照,下面這篇文章主要給大家介紹了關(guān)于Java中工具Jstack使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Java面試題 從源碼角度分析HashSet實(shí)現(xiàn)原理

    Java面試題 從源碼角度分析HashSet實(shí)現(xiàn)原理

    這篇文章主要介紹了Java面試題 從源碼角度分析HashSet實(shí)現(xiàn)原理?,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 一文詳解如何在SpringMVC的視圖中渲染模型數(shù)據(jù)

    一文詳解如何在SpringMVC的視圖中渲染模型數(shù)據(jù)

    SpringMVC是一個(gè)基于Spring框架的Web框架,它提供了一種方便的方式來(lái)處理 HTTP 請(qǐng)求和響應(yīng),在SpringMVC中,視圖是用來(lái)渲染模型數(shù)據(jù)的組件,它們負(fù)責(zé)將模型數(shù)據(jù)轉(zhuǎn)換為HTML、JSON、XML等格式的響應(yīng),在本文中,我們將討論如何在SpringMVC中的視圖中渲染模型數(shù)據(jù)
    2023-07-07
  • java實(shí)現(xiàn)雪花算法ID生成器工具類

    java實(shí)現(xiàn)雪花算法ID生成器工具類

    本文主要介紹了java實(shí)現(xiàn)雪花算法ID生成器工具類,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07

最新評(píng)論

土默特右旗| 洛扎县| 富源县| 怀柔区| 靖安县| 隆林| 灵武市| 滦南县| 綦江县| 瓦房店市| 噶尔县| 新竹县| 高邮市| 新安县| 汝州市| 大方县| 仪陇县| 弋阳县| 金坛市| 库车县| 安岳县| 陆川县| 黑龙江省| 贡觉县| 偏关县| 石门县| 理塘县| 渝中区| 珲春市| 清原| 沽源县| 涟水县| 临湘市| 新沂市| 铜鼓县| 武清区| 通辽市| 容城县| 天峻县| 贡觉县| 霍林郭勒市|