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

        共 19702字,需瀏覽 40分鐘

         ·

        2024-04-19 14:44

        大家好,我是二哥呀。

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

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

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

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

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

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

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

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

        技術(shù)派首頁(yè)

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

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

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

        手畫Netty原理和流程

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

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

        Netty 官方架構(gòu)圖

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

        碼海:Netty 的樣子

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

        ①、主 Reactor 線程組(Boss Group)

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

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

        當(dāng) BossGroup 的 Selector 接收到連接請(qǐng)求時(shí),使用 ServerSocketChannel.accept() 方法來接受新連接。

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

        ②、從 Reactor 線程組(Worker Group)

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

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

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

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

        請(qǐng)說一下 Netty 的工作流程?

        下面是一個(gè)簡(jiǎn)單的 Netty 服務(wù)器和客戶端的示例,展示了基本的工作流程。這個(gè)例子中,服務(wù)器接收字符串消息,轉(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:

        服務(wù)器初始化時(shí),首先創(chuàng)建兩個(gè) NioEventLoopGroup 實(shí)例。

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

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

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

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

        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:客戶端只需要一個(gè) NioEventLoopGroup 來處理所有操作,包括創(chuàng)建連接、發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。

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

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

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

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

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

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

        簡(jiǎn)單來說,JDK 包含 JRE,JRE 包含 JVM。

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

        如何排查OOM?

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

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

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

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

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

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

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

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

        三分惡面渣逆襲:JConsole概覽

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

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

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

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

        還有一些第三方的工具:

        ①、MAT

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

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

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

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

        ⑤、arthas

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

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

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

        Java 緩沖區(qū)溢出主要是由于向緩沖區(qū)寫入的數(shù)據(jù)超過其能夠存儲(chǔ)的數(shù)據(jù)量??梢圆捎眠@些措施來避免:

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

        ②、控制寫入數(shù)據(jù)量:在向緩沖區(qū)寫入數(shù)據(jù)時(shí),應(yīng)該控制寫入的數(shù)據(jù)量,確保不會(huì)超過緩沖區(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è)置一個(gè)合理的緩沖區(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.");
                }

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

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

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

        進(jìn)程和線程的區(qū)別

        進(jìn)程說簡(jiǎn)單點(diǎn)就是我們?cè)陔娔X上啟動(dòng)的一個(gè)個(gè)應(yīng)用,比如我們啟動(dòng)一個(gè)瀏覽器,就會(huì)啟動(dòng)了一個(gè)瀏覽器進(jìn)程。進(jìn)程是操作系統(tǒng)資源分配的最小單位,它包括了程序、數(shù)據(jù)和進(jìn)程控制塊等。

        線程說簡(jiǎn)單點(diǎn)就是我們?cè)?Java 程序中啟動(dòng)的一個(gè) main 線程,一個(gè)進(jìn)程至少會(huì)有一個(gè)線程。當(dāng)然了,我們也可以啟動(dòng)多個(gè)線程,比如說一個(gè)線程進(jìn)行 IO 讀寫,一個(gè)線程進(jìn)行加減乘除計(jì)算,這樣就可以充分發(fā)揮多核 CPU 的優(yōu)勢(shì),因?yàn)?IO 讀寫相對(duì) CPU 計(jì)算來說慢得多。線程是 CPU 分配資源的基本單位。

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

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

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

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

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

        ①、先來先服務(wù)

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

        三分惡面渣逆襲:先來先服務(wù)

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

        選擇預(yù)計(jì)運(yùn)行時(shí)間最短的進(jìn)程優(yōu)先執(zhí)行。這種方式可以減少平均等待時(shí)間和響應(yīng)時(shí)間,但缺點(diǎn)是很難準(zhǔn)確預(yù)知進(jìn)程的執(zhí)行時(shí)間,并且可能因?yàn)槎套鳂I(yè)一直在執(zhí)行,導(dǎo)致長(zhǎng)作業(yè)持續(xù)被推遲執(zhí)行。

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

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

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

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

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

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

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

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

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

        參考鏈接

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

        ending

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

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

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

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

        瀏覽 150
        10點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        10點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 色妞女女女女女BBBB | 欧美美女被日 | 91成年人在线观看 | 日本色色色| 国产啊~cao死你个小sao货 |