<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          華為又招了一名天才少年。

          共 19702字,需瀏覽 40分鐘

           ·

          2024-04-19 14:44

          大家好,我是二哥呀。

          今天在微信看一看中刷到一條電子科技大學的帖子:“華為天才少年+1”,這應該是 2024 年我看到的第一個公開資料的天才少年,蕪湖,又一個百萬年薪選手即將登場。

          劉順程,本科畢業(yè)于重慶郵電大學,2020 年獲得電子科技大學碩博連讀。郵電、成電的同學們看到這是不是又多了幾分學習的熱情?

          要知道,華為天才少年要經(jīng)歷十幾輪的面試篩選,要求非??量?,我只能說成電還是牛的啊。劉同學剛畢業(yè)就能拿到百萬年薪,人生也算是走上了一個新的高度。

          相信有不少同學對華為是情有獨鐘,那今天繼續(xù)給大家分享一個 Java 面試指南中《華為面經(jīng)-同學 9》的通用軟件開發(fā)一面原題,來看看華為面試官都喜歡問哪些問題,好做到知彼知己百戰(zhàn)不殆。

          內(nèi)容較長,建議正在準備 24 屆春招和 25 屆暑期實習、秋招的同學先收藏起來,面試的時候大概率會碰到,我會盡量用通俗易懂+手繪圖的方式,讓天下所有的面渣都能逆襲 ??

          華為面經(jīng)(詳細)

          介紹項目,技術(shù)選型主要問了MySQL、Redis、RabbitMQ

          技術(shù)派是一個基于 Spring Boot、MyBatis-Plus、MySQL、Redis、ElasticSearch、MongoDB、Docker、RabbitMQ 等技術(shù)棧實現(xiàn)的社區(qū)系統(tǒng)。

          技術(shù)派首頁

          這個系統(tǒng)旨在為創(chuàng)作者提供一個可以發(fā)布文章和教程,并賺取傭金的社區(qū)平臺,同時又兼顧一些社交屬性,比如說用戶可以通過閱讀、點贊、收藏、評論的形式和作者互動。

          與此同時,為了緊跟時代潮流,該系統(tǒng)還為用戶提供了一套基于 OpenAI、訊飛星火等多家大模型的派聰明 AI 助手,幫助用戶在工作和學習中大幅提效。

          選擇 MySQL 是因為它是互聯(lián)網(wǎng)主流的關(guān)系型數(shù)據(jù)庫,能夠幫助我在工作后快速承接公司的開發(fā)任務;而 Redis 作為緩存中間件,支持集群、分片,單機就可以支持數(shù)十萬 QPS,可以大大提高系統(tǒng)性能;選擇 RabbitMQ 是因為社區(qū)活躍度高,然后 RabbitMQ 還提供了一個易用的用戶界面,可以讓用戶監(jiān)控和管理消息。

          手畫Netty原理和流程

          Netty 是一個基于Java NIO的高性能異步事件驅(qū)動的網(wǎng)絡(luò)應用框架,極大簡化了網(wǎng)絡(luò)編程的復雜性。

          常用于構(gòu)建 RPC 框架,以提升分布式服務之間的通信效率。像 Dubbo 的網(wǎng)絡(luò)層就可以基于 Netty 來實現(xiàn)。

          Netty 官方架構(gòu)圖

          Netty 支持零拷貝、可拓展事件模型;支持 TCP、UDP、HTTP、WebSocket 等多種協(xié)議;提供安全傳輸、可壓縮、大文件、編解碼等多種功能。

          碼海:Netty 的樣子

          Netty 是基于主從 Reactor 模式實現(xiàn)的,主要分為兩個線程組:

          ①、主 Reactor 線程組(Boss Group)

          負責處理新的客戶端連接請求。它內(nèi)部維護一個或多個線程,每個線程都包含一個 Selector。

          ServerSocketChannel 注冊到 BossGroup 的 Selector 上,只關(guān)注 OP_ACCEPT 事件,即新的連接建立請求。

          當 BossGroup 的 Selector 接收到連接請求時,使用 ServerSocketChannel.accept() 方法來接受新連接。

          接受到的新連接被封裝為 NioSocketChannel,并注冊到 Worker Group 的 Selector 上。

          ②、從 Reactor 線程組(Worker Group)

          WorkerGroup 管理的線程可能有多個,每個線程也是維護自己的 Selector。Netty 通常會根據(jù)一定的策略(如輪詢)選擇一個 Selector 來平衡負載。

          每個 Selector 負責監(jiān)聽和處理所有已注冊的 NioSocketChannel 的 IO 事件,如讀 (OP_READ)、寫 (OP_WRITE) 事件等。

          當事件發(fā)生時,相應的 ChannelHandler 被調(diào)用來處理這些事件。這些 Handler 可以是用戶自定義的處理器,用于實現(xiàn)具體的業(yè)務邏輯。

          碼海:Netty 工作架構(gòu)圖

          請說一下 Netty 的工作流程?

          下面是一個簡單的 Netty 服務器和客戶端的示例,展示了基本的工作流程。這個例子中,服務器接收字符串消息,轉(zhuǎn)換為大寫形式后返回給客戶端。

          NettyServer:

          public class NettyServer {
              private final int port;

              public NettyServer(int port) {
                  this.port = port;
              }

              public void start() throws Exception {
                  EventLoopGroup bossGroup = new NioEventLoopGroup();
                  EventLoopGroup workerGroup = new NioEventLoopGroup();
                  try {
                      ServerBootstrap bootstrap = new ServerBootstrap();
                      bootstrap.group(bossGroup, workerGroup)
                               .channel(NioServerSocketChannel.class)
                               .childHandler(new ChannelInitializer<SocketChannel>() 
          {
                                   @Override
                                   protected void initChannel(SocketChannel ch) throws Exception {
                                       ch.pipeline().addLast(new StringDecoder());
                                       ch.pipeline().addLast(new StringEncoder());
                                       ch.pipeline().addLast(new ServerHandler());
                                   }
                               })
                               .option(ChannelOption.SO_BACKLOG, 128)
                               .childOption(ChannelOption.SO_KEEPALIVE, true);

                      ChannelFuture future = bootstrap.bind(port).sync();
                      System.out.println("Server started on port " + port);
                      future.channel().closeFuture().sync();
                  } finally {
                      workerGroup.shutdownGracefully();
                      bossGroup.shutdownGracefully();
                  }
              }

              public static void main(String[] args) throws Exception {
                  new NettyServer(8080).start();
              }

              static class ServerHandler extends ChannelInboundHandlerAdapter {
                  @Override
                  public void channelRead(ChannelHandlerContext ctx, Object msg) {
                      String input = (String) msg;
                      System.out.println("Received: " + input);
                      ctx.writeAndFlush(input.toUpperCase());
                  }

                  @Override
                  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                      cause.printStackTrace();
                      ctx.close();
                  }
              }
          }

          ①、BossGroup 和 WorkerGroup:

          服務器初始化時,首先創(chuàng)建兩個 NioEventLoopGroup 實例。

          BossGroup 用于接受客戶端的連接,WorkerGroup 用于處理連接后的數(shù)據(jù)傳輸。

          • BossGroup 監(jiān)聽端口上的連接請求,每當接收到新連接時,BossNioEventLoop 就會處理連接請求,接受連接,并將新的 SocketChannel 注冊到 WorkerGroup 的一個 NioEventLoop 上。
          • 當 WorkerGroup 的 NioEventLoop 監(jiān)測到 IO 事件(如讀取數(shù)據(jù)),它會根據(jù)注冊的 ChannelPipeline 中的 ChannelHandlers 處理這些事件。在示例中,服務器端收到數(shù)據(jù)后,通過一個 ServerHandler 將數(shù)據(jù)轉(zhuǎn)換為大寫并返回給客戶端。

          ②、ServerBootstrap:配置服務器使用的輔助啟動類。設(shè)置服務器要使用的 channel 類型為 NioServerSocketChannel。

          并為新接入的連接定義 ChannelInitializer,在這個初始化器中,配置 ChannelPipeline,包括編解碼器和業(yè)務處理器。

          NettyClient:

          public class NettyClient {
              private final String host;
              private final int port;

              public NettyClient(String host, int port) {
                  this.host = host;
                  this.port = port;
              }

              public void start() throws Exception {
                  EventLoopGroup group = new NioEventLoopGroup();
                  try {
                      Bootstrap bootstrap = new Bootstrap();
                      bootstrap.group(group)
                              .channel(NioSocketChannel.class)
                              .handler(new ChannelInitializer<SocketChannel>() 
          {
                                  @Override
                                  protected void initChannel(SocketChannel ch) throws Exception {
                                      ch.pipeline().addLast(new StringDecoder());
                                      ch.pipeline().addLast(new StringEncoder());
                                      ch.pipeline().addLast(new ClientHandler());
                                  }
                              });

                      Channel channel = bootstrap.connect(host, port).sync().channel();
                      Scanner scanner = new Scanner(System.in);
                      while (true) {
                          String line = scanner.nextLine();
                          if ("quit".equalsIgnoreCase(line)) {
                              channel.close();
                              break;
                          }
                          channel.writeAndFlush(line);
                      }
                      channel.closeFuture().sync();
                  } finally {
                      group.shutdownGracefully();
                  }
              }

              public static void main(String[] args) throws Exception {
                  new NettyClient("localhost"8080).start();
              }

              static class ClientHandler extends SimpleChannelInboundHandler<String{
                  @Override
                  protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                      System.out.println("Received from server: " + msg);
                  }

                  @Override
                  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                      cause.printStackTrace();
                      ctx.close();
                  }
              }
          }

          ①、EventLoopGroup:客戶端只需要一個 NioEventLoopGroup 來處理所有操作,包括創(chuàng)建連接、發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。

          ②、Bootstrap:配置客戶端使用的輔助啟動類。設(shè)置客戶端要使用的 channel 類型為 NioSocketChannel。

          客戶端使用 Scanner 從命令行讀取用戶輸入,發(fā)送到服務器;同時,它也能接收服務器返回的數(shù)據(jù),并通過 ClientHandler 打印到控制臺。

          JRE與JDK的區(qū)別,JDK多了哪些東西,既安裝了JRE又安裝了JDK,可以利用JDK做什么事情?

          JVM:Java Virtual Machine,也就是 Java 虛擬機,是 Java 實現(xiàn)跨平臺的關(guān)鍵所在,針對不同的操作系統(tǒng),有不同的 JVM 實現(xiàn)。JVM 負責將 Java 字節(jié)碼轉(zhuǎn)換為特定平臺的機器碼,并執(zhí)行。

          JRE:Java Runtime Environment,也就是 Java 運行時環(huán)境,包含了運行 Java 程序所必需的庫,以及 Java 虛擬機(JVM)。

          JDK:Java Development Kit,是一套完整的 Java SDK(軟件開發(fā)工具包),包括了 JRE 以及編譯器(javac)、Java 文檔生成工具(Javadoc)、Java 調(diào)試器等開發(fā)工具。為開發(fā)者提供了開發(fā)、編譯、調(diào)試 Java 程序的一整套環(huán)境。

          簡單來說,JDK 包含 JRE,JRE 包含 JVM。

          三分惡面渣逆襲:JDK、JRE、JVM關(guān)系

          如何排查OOM?

          內(nèi)存溢出(Out of Memory,俗稱 OOM)是指當程序請求分配內(nèi)存時,由于沒有足夠的內(nèi)存空間滿足其需求,從而觸發(fā)的錯誤。

          首先,我會通過異常信息和日志確定OOM的類型。Java的OOM錯誤通常有幾種類型,如堆內(nèi)存溢出、Metaspace溢出或直接內(nèi)存溢出。比如,如果日志中顯示“java.lang.OutOfMemoryError: Java heap space”,那就說明是堆內(nèi)存溢出。

          一旦確定了是堆內(nèi)存溢出,我會使用 JConsole 實時監(jiān)控JVM的內(nèi)存使用情況,特別是那些占用大量內(nèi)存的對象和類。

          找到可能的內(nèi)存泄漏源后,我會回到代碼中去,查找和修復具體的問題。

          之后,我會在本地進行壓力測試,模擬高負載情況下的內(nèi)存表現(xiàn),確保修改有效,且沒有引入新的問題。

          如何查看當前Java程序里哪些對象正在使用,哪些對象已經(jīng)被釋放

          在 Java 程序中,查看哪些對象正在使用和哪些已經(jīng)被釋放的方法主要涉及運行時的內(nèi)存監(jiān)控和分析。需要借助一些專門的工具來進行:

          ①、JConsole:JDK 自帶的監(jiān)控工具,可以用來監(jiān)視 Java 應用程序的運行狀態(tài),包括內(nèi)存使用、線程狀態(tài)、類加載、GC 等,還可以進行一些基本的性能分析。

          三分惡面渣逆襲:JConsole概覽

          ②、VisualVM:VisualVM 是一個基于 NetBeans 平臺的可視化工具,在很長一段時間內(nèi),VisualVM 都是 Oracle 官方主推的故障處理工具。集成了多個 JDK 命令行工具的功能,提供了一個友好的圖形界面,非常適用于開發(fā)和生產(chǎn)環(huán)境。

          三分惡面渣逆襲:VisualVM安裝插件

          ③、Java Mission Control:JMC 最初是 JRockit VM 中的診斷工具,但在 Oracle JDK7 Update 40 以后,就綁定到了 HotSpot VM 中。不過后來又被 Oracle 開源出來作為一個單獨的產(chǎn)品。

          三分惡面渣逆襲:JMC主要界面

          還有一些第三方的工具:

          ①、MAT

          • Java 堆內(nèi)存分析工具,主要用于分析和查找 Java 堆中的內(nèi)存泄漏和內(nèi)存消耗問題。
          • 可以從 Java 堆轉(zhuǎn)儲文件中分析內(nèi)存使用情況,并提供豐富的報告,如內(nèi)存泄漏疑點、最大對象和 GC 根信息。
          • 支持通過圖形界面查詢對象,以及檢查對象間的引用關(guān)系。

          ②、GChisto:GC 日志分析工具,幫助開發(fā)者優(yōu)化垃圾收集行為和調(diào)整 GC 性能。

          ③、GCViewer:類似于 GChisto,也是用來分析 GC 日志,幫助開發(fā)者優(yōu)化 Java 應用的垃圾回收過程。

          ④、JProfiler:一個全功能的商業(yè) Java 性能分析工具,提供 CPU、 內(nèi)存和線程的實時分析。

          ⑤、arthas

          • 阿里巴巴開源的 Java 診斷工具,主要用于線上的應用診斷。
          • 支持在不停機的情況下進行 Java 應用的診斷。
          • 包括 JVM 信息查看、監(jiān)控、Trace 命令、反編譯等。

          ⑥、async-profiler:一個低開銷的性能分析工具,支持生成火焰圖,適用于復雜性能問題的分析。

          Java緩沖區(qū)溢出,如何預防

          Java 緩沖區(qū)溢出主要是由于向緩沖區(qū)寫入的數(shù)據(jù)超過其能夠存儲的數(shù)據(jù)量。可以采用這些措施來避免:

          ①、合理設(shè)置緩沖區(qū)大小:在創(chuàng)建緩沖區(qū)時,應根據(jù)實際需求合理設(shè)置緩沖區(qū)的大小,避免創(chuàng)建過大或過小的緩沖區(qū)。

          ②、控制寫入數(shù)據(jù)量:在向緩沖區(qū)寫入數(shù)據(jù)時,應該控制寫入的數(shù)據(jù)量,確保不會超過緩沖區(qū)的容量。Java 的 ByteBuffer 類提供了remaining()方法,可以獲取緩沖區(qū)中剩余的可寫入數(shù)據(jù)量。

          import java.nio.ByteBuffer;

          public class ByteBufferExample {

              public static void main(String[] args) {
                  // 模擬接收到的數(shù)據(jù)
                  byte[] receivedData = {12345};
                  int bufferSize = 1024;  // 設(shè)置一個合理的緩沖區(qū)大小

                  // 創(chuàng)建ByteBuffer
                  ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

                  // 寫入數(shù)據(jù)之前檢查容量是否足夠
                  if (buffer.remaining() >= receivedData.length) {
                      buffer.put(receivedData);
                  } else {
                      System.out.println("Not enough space in buffer to write data.");
                  }

                  // 準備讀取數(shù)據(jù):將limit設(shè)置為當前位置,position設(shè)回0
                  buffer.flip();

                  // 讀取數(shù)據(jù)
                  while (buffer.hasRemaining()) {
                      byte data = buffer.get();
                      System.out.println("Read data: " + data);
                  }

                  // 清空緩沖區(qū)以便再次使用
                  buffer.clear();
              }
          }

          進程和線程的區(qū)別

          進程說簡單點就是我們在電腦上啟動的一個個應用,比如我們啟動一個瀏覽器,就會啟動了一個瀏覽器進程。進程是操作系統(tǒng)資源分配的最小單位,它包括了程序、數(shù)據(jù)和進程控制塊等。

          線程說簡單點就是我們在 Java 程序中啟動的一個 main 線程,一個進程至少會有一個線程。當然了,我們也可以啟動多個線程,比如說一個線程進行 IO 讀寫,一個線程進行加減乘除計算,這樣就可以充分發(fā)揮多核 CPU 的優(yōu)勢,因為 IO 讀寫相對 CPU 計算來說慢得多。線程是 CPU 分配資源的基本單位。

          三分惡面渣逆襲:進程與線程關(guān)系

          一個進程中可以有多個線程,多個線程共用進程的堆和方法區(qū)(Java 虛擬機規(guī)范中的一個定義,JDK 8 以后的實現(xiàn)為元空間)資源,但是每個線程都會有自己的程序計數(shù)器和棧。

          進程的調(diào)度方式

          進程調(diào)度是操作系統(tǒng)中的核心功能之一,它負責決定哪些進程在何時使用 CPU。這一決定基于系統(tǒng)中的進程調(diào)度算法。

          三分惡面渣逆襲:進程調(diào)度算法

          ①、先來先服務

          這是最簡單的調(diào)度算法,也稱為先進先出(FIFO)。進程按照請求 CPU 的順序進行調(diào)度。這種方式易于實現(xiàn),但可能會導致較短的進程等待較長進程執(zhí)行完成,從而產(chǎn)生“饑餓”現(xiàn)象。

          三分惡面渣逆襲:先來先服務

          ②、短作業(yè)優(yōu)先

          選擇預計運行時間最短的進程優(yōu)先執(zhí)行。這種方式可以減少平均等待時間和響應時間,但缺點是很難準確預知進程的執(zhí)行時間,并且可能因為短作業(yè)一直在執(zhí)行,導致長作業(yè)持續(xù)被推遲執(zhí)行。

          三分惡面渣逆襲:短作業(yè)優(yōu)先

          ③、優(yōu)先級調(diào)度

          在這種調(diào)度方式中,每個進程都被分配一個優(yōu)先級。CPU 首先分配給優(yōu)先級最高的進程。優(yōu)先級調(diào)度可以是非搶占式的或搶占式的。在非搶占式優(yōu)先級調(diào)度中,進程一旦開始執(zhí)行將一直運行直到完成;在搶占式優(yōu)先級調(diào)度中,更高優(yōu)先級的進程可以中斷正在執(zhí)行的低優(yōu)先級進程。

          三分惡面渣逆襲:優(yōu)先級調(diào)度

          ④、時間片輪轉(zhuǎn)

          時間片輪轉(zhuǎn)調(diào)度為每個進程分配一個固定的時間段,稱為時間片,進程可以在這個時間片內(nèi)運行。如果進程在時間片結(jié)束時還沒有完成,它將被放回隊列的末尾。時間片輪轉(zhuǎn)是公平的調(diào)度方式,可以保證所有進程得到公平的 CPU 時間,適用于共享系統(tǒng)。

          三分惡面渣逆襲:時間片輪轉(zhuǎn)

          ⑤、最短剩余時間優(yōu)先

          這是短作業(yè)優(yōu)先的一種改進形式,它是搶占式的。即如果一個新進程的預計執(zhí)行時間比當前運行進程的剩余時間短,調(diào)度器將暫停當前的進程,并切換到新進程。這種方法也可以最小化平均等待時間,但同樣面臨預測執(zhí)行時間的困難。

          參考鏈接

          • 三分惡的面渣逆襲:https://javabetter.cn/sidebar/sanfene/nixi.html
          • 二哥的 Java 進階之路:https://javabetter.cn

          ending

          一個人可以走得很快,但一群人才能走得更遠。二哥的編程星球已經(jīng)有 5100 多名球友加入了,如果你也需要一個良好的學習環(huán)境,戳鏈接 ?? 加入我們吧。這是一個編程學習指南 + Java 項目實戰(zhàn) + LeetCode 刷題的私密圈子,你可以閱讀星球?qū)凇⑾蚨缣釂?、幫你制定學習計劃、和球友一起打卡成長。

          兩個置頂帖「球友必看」和「知識圖譜」里已經(jīng)沉淀了非常多優(yōu)質(zhì)的學習資源,相信能幫助你走的更快、更穩(wěn)、更遠。

          歡迎點擊左下角閱讀原文了解二哥的編程星球,這可能是你學習求職路上最有含金量的一次點擊。

          最后,把二哥的座右銘送給大家:沒有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不系之舟。共勉 ??。

          瀏覽 150
          10點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          10點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产黄色片精品AAWWW | 国产熟女一区 | www欧美日韩 | 韩国成人精品三级 | 国产精品久久久久久无码红治院 |