Java并發編程 - Executor,Executors,ExecutorService, CompletionServie,Future,Callable

一、Exectuor框架簡介?? ? ?

?Java從1.5版本開始,為簡化多線程并發編程,引入全新的并發編程包:java.util.concurrent及其并發編程框架(Executor框架)。?Executor框架是指java 5中引入的一系列并發庫中與executor相關的一些功能類,其中包括線程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。他們的關系為? ?

??

?

?

在Executor框架中,使用執行器(Exectuor)來管理Thread對象,從而簡化了并發編程。

?

二、認識Exectuor(執行器)

1、并發編程的一種編程方式是把任務拆分為一系列的小任務,即Runnable,然后將這些任務提交給一個Executor執行,Executor.execute(Runnalbe)?。Executor在執行時使用其內部的線程池來完成操作。

? ? ? Executor的子接口有:ExecutorService,ScheduledExecutorService,已知實現類:AbstractExecutorService,ScheduledThreadPoolExecutor,ThreadPoolExecutor。

?

2、Executor屬于public類型的接口。可以用于提交,管理或者執行Runnable任務。實現Executor接口的class還可以控制Runnable任務執行線程的具體細節。包括線程使用的細節、調度等。一般來說,Runnable任務開辟在新線程中的使用方法為:new Thread(new RunnableTask())).start()

?

3、但在Executor中,可以使用Executor而不用顯示地創建線程。例如,可以使用以下方法創建線程,而不是像第2點中為一種任務中的每個任務都調用new Thread(...)的方法。

?

Java代碼??收藏代碼
  1. Exectuor?executor?=?anExecutor();??
  2. executor.execute(new?RunnableTask());?//?異步執行??
  3. executor.execute(new?RunnableTask());??

?

?

?

4、但是,Executor接口并沒有嚴格地要求執行必須是異步/同步的,一切都相當自由。在最簡單的情況下,執行程序可以在調用者的線程中立即運行已提交的任務,

?

Java代碼??收藏代碼
  1. class?DirectExecutor?implements?Executor?{????????
  2. ???????public?void?execute(Runnable?r)?{????????????
  3. ??????????????r.run();??????
  4. ???????}????
  5. }??

?更常見的是,任務在某個不是調用者線程的線程中執行的。如在另一個線程中啟動:

?

Java代碼??收藏代碼
  1. class?ThreadPerTaskExecutor?implements?Executor?{????????
  2. ???????????public?void?execute(Runnable?r)?{????????????
  3. ??????????????new?Thread(r).start();????????
  4. ????????????}????
  5. }??

?

?

?也可以在實現中用另一個Executor來序列化執行過程:

?

Java代碼??收藏代碼
  1. class?SerialExecutor?implements?Executor?{????
  2. ????final?Queue<Runnable>?tasks?=?new?ArrayDeque<Runnable>();????
  3. ????final?Executor?executor;????
  4. ????Runnable?active;????
  5. ????
  6. ????SerialExecutor(Executor?executor)?{????
  7. ????????this.executor?=?executor;????
  8. ????}????
  9. ????
  10. ????public?synchronized?void?execute(final?Runnable?r)?{????
  11. ????????tasks.offer(new?Runnable()?{????
  12. ????????????public?void?run()?{????
  13. ????????????????try?{????
  14. ????????????????????r.run();????
  15. ????????????????}?finally?{????
  16. ????????????????????scheduleNext();????
  17. ????????????????}????
  18. ????????????}????
  19. ????????});????
  20. ????????if?(active?==?null)?{????
  21. ????????????scheduleNext();????
  22. ????????}????
  23. ????}????
  24. ????
  25. ????protected?synchronized?void?scheduleNext()?{????
  26. ????????if?((active?=?tasks.poll())?!=?null)?{????
  27. ????????????executor.execute(active);????
  28. ????????}????
  29. ????}????
  30. }????

?

?

?

?

?5、ThreadPoolExecutor類提供了一個可供可擴展的線程池實現。Executors類為Executor接口及其實現提供了便捷的工廠方法。

?

6、 Executor中的方法execute。void execute(Runnable command)表示在未來的某個時間執行給定的命令。該命令可能在新的線程、已經入池的線程或者正在調用的線程中執行。

?

三、Executors類: 主要用于提供線程池相關的操作

Executors類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了ExecutorService接口。

?1、public static ExecutorService newFiexedThreadPool(int Threads)?創建固定數目線程的線程池。

?

2、public static ExecutorService newCachedThreadPool():創建一個可緩存的線程池,調用execute 將重用以前構造的線程(如果線程可用)。如果沒有可用的線程,則創建一個新線程并添加到池中。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程。

?

3、public static ExecutorService newSingleThreadExecutor():創建一個單線程化的Executor。

?

4、public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

創建一個支持定時及周期性的任務執行的線程池,多數情況下可用來替代Timer類。

?

?四、ExecutorService與生命周期

?

1、ExecutorService可以理解為程序員提供了一堆操作Executor的API

?

2、ExecutorService擴展了Executor并添加了一些生命周期管理的方法。一個Executor的生命周期有三種狀態

運行、關閉和終止。

? ? ?Executor創建時處于運行狀態。當調用ExecutorService.shutdown()后,處于關閉狀態,isShutdown()方法返回true。這時,不應該再向Executor中添加任務,所有已添加的任務執行完畢后,Executor處于終止狀態,isTerminated()返回true。如果Executor處于關閉狀態,往Executor提交任務會拋出unchecked exception RejectedExecutionException。

?

3、本質

? ? 接口ExecutorService 表述了異步執行的機制,并且可以讓任務在后臺執行。一個ExecutorService 實例因此特別像一個線程池。事實上,在 java.util.concurrent 包中的 ExecutorService 的實現就是一個線程池的實現。

?

Java代碼??收藏代碼
  1. ExecutorService?executorService?=?Executors.newFixedThreadPool(10);??
  2. ???
  3. executorService.execute(new?Runnable()?{??
  4. ????public?void?run()?{??
  5. ????????System.out.println("Asynchronous?task");??
  6. ????}??
  7. });??
  8. ???
  9. executorService.shutdown();??

?

?

? ?該示例代碼首先使用 newFixedThreadPool() 工廠方法創建一個ExecutorService ,上述代碼創建了一個可以容納10個線程任務的線程池。其次,向 execute() 方法中傳遞一個異步的 Runnable 接口的實現,這樣做會讓 ExecutorService 中的某個線程執行這個Runnable 線程。

?

4、任務的委托

下方展示了一個線程的把任務委托異步執行的ExecutorService的示意圖。



?一旦線程把任務委托給 ExecutorService,該線程就會繼續執行與運行任務無關的其它任務。

?

5、ExecutorService 的實現

由于 ExecutorService 只是一個接口,ExecutorService 接口在 java.util.concurrent 包中有如下實現類:

  • ThreadPoolExecutor
  • ScheduledThreadPoolExecutor

6、ExecutorService 使用方法

這里有幾種不同的方式讓你將任務委托給一個ExecutorService:

?

Java代碼??收藏代碼
  1. execute(Runnable)??
  2. submit(Runnable)??
  3. submit(Callable)??
  4. invokeAny()??
  5. invokeAll()??

?

?

7、execute(Runnable)

方法 execute(Runnable) 接收一個java.lang.Runnable 對象作為參數,并且以異步的方式執行它。如下是一個使用 ExecutorService 執行 Runnable 的例子:

?

Java代碼??收藏代碼
  1. ExecutorService?executorService?=?Executors.newSingleThreadExecutor();??
  2. ???
  3. executorService.execute(new?Runnable()?{??
  4. ????public?void?run()?{??
  5. ????????System.out.println("Asynchronous?task");??
  6. ????}??
  7. });??
  8. ???????
  9. executorService.shutdown();??

使用這種方式沒有辦法獲取執行 Runnable 之后的結果,如果你希望獲取運行之后的返回值,就必須使用接收 Callable 參數的 execute() 方法。接下來會提到。

?

?

8、submit(Runnable)

方法 submit(Runnable) 同樣接收一個Runnable 的實現作為參數,但是會返回一個Future 對象。這個Future 對象可以用于判斷 Runnable 是否結束執行。如下是一個ExecutorService 的 submit() 方法的例子:

?

Java代碼??收藏代碼
  1. Future?future?=?executorService.submit(new?Runnable()?{??
  2. ????public?void?run()?{??
  3. ????????System.out.println("Asynchronous?task");??
  4. ????}??
  5. });??
  6. //如果任務結束執行則返回?null??
  7. System.out.println("future.get()="?+?future.get());??

?

?

9、submit(Callable)

方法 submit(Callable) 和方法 submit(Runnable) 比較類似,但是區別則在于它們接收不同的參數類型。Callable 的實例與 Runnable 的實例很類似,但是 Callable 的 call() 方法可以返回一個結果。方法 Runnable.run() 則不能返回結果。

Callable 的返回值可以從方法 submit(Callable) 返回的 Future 對象中獲取。如下是一個 ExecutorService Callable 的樣例:

?

Java代碼??收藏代碼
  1. Future?future?=?executorService.submit(new?Callable(){??
  2. ????public?Object?call()?throws?Exception?{??
  3. ????????System.out.println("Asynchronous?Callable");??
  4. ????????return?"Callable?Result";??
  5. ????}??
  6. });??
  7. ???
  8. System.out.println("future.get()?=?"?+?future.get());??

?上述樣例代碼會輸出如下結果:

?

Java代碼??收藏代碼
  1. Asynchronous?Callable??
  2. future.get()?=?Callable?Result??

?

10、inVokeAny()

方法 invokeAny() 接收一個包含 Callable 對象的集合作為參數。調用該方法不會返回 Future 對象,而是返回集合中某一個Callable 對象的結果,而且無法保證調用之后返回的結果是哪一個 Callable,只知道它是這些 Callable 中一個執行結束的 Callable 對象。如果一個任務運行完畢或者拋出異常,方法會取消其它的 Callable 的執行。
以下是一個樣例:

Java代碼??收藏代碼
  1. ExecutorService?executorService?=?Executors.newSingleThreadExecutor();??
  2. ???
  3. Set<Callable<String>>?callables?=?new?HashSet<Callable<String>>();??
  4. ???
  5. callables.add(new?Callable<String>()?{??
  6. ????public?String?call()?throws?Exception?{??
  7. ????????return?"Task?1";??
  8. ????}??
  9. });??
  10. callables.add(new?Callable<String>()?{??
  11. ????public?String?call()?throws?Exception?{??
  12. ????????return?"Task?2";??
  13. ????}??
  14. });??
  15. callables.add(new?Callable<String>()?{??
  16. ????public?String?call()?throws?Exception?{??
  17. ????????return?"Task?3";??
  18. ????}??
  19. });??
  20. ???
  21. String?result?=?executorService.invokeAny(callables);??
  22. ???
  23. System.out.println("result?=?"?+?result);??
  24. ???
  25. executorService.shutdown();??

?以上樣例代碼會打印出在給定的集合中的某一個Callable 的返回結果。嘗試運行后發現每次結果都在改變。有時候返回結果是"Task 1",有時候是"Task 2",等等。

?

11、invokeAll()

方法 invokeAll() 會調用存在于參數集合中的所有 Callable 對象,并且返回一個包含 Future 對象的集合,你可以通過這個返回的集合來管理每個 Callable 的執行結果。需要注意的是,任務有可能因為異常而導致運行結束,所以它可能并不是真的成功運行了。但是我們沒有辦法通過 Future 對象來了解到這個差異。

12、ExecutorService服務的關閉

? ? ? 當使用 ExecutorService 完畢之后,我們應該關閉它,這樣才能保證線程不會繼續保持運行狀態。?
? ? ? 舉例來說,如果你的程序通過 main() 方法啟動,并且主線程退出了你的程序,如果還有一個活動的 ExecutorService 存在于程序中,那么程序將會繼續保持運行狀態。存在于 ExecutorService 中的活動線程會阻止Java虛擬機關閉。?
? ? ? 為了關閉在 ExecutorService 中的線程,需要調用 shutdown() 方法。但ExecutorService 并不會馬上關閉,而是不再接收新的任務,一旦所有的線程結束執行當前任務,ExecutorServie 才會真的關閉。所有在調用 shutdown() 方法之前提交到 ExecutorService 的任務都會執行。?
? ? ?如果你希望立即關閉 ExecutorService,你可以調用 shutdownNow() 方法。這個方法會嘗試馬上關閉所有正在執行的任務,并且跳過所有已經提交但是還沒有運行的任務。但是對于正在執行的任務,是否能夠成功關閉它是無法保證的,有可能他們真的被關閉掉了,也有可能它會一直執行到任務結束。這是一個最好的嘗試。

?

五、CompletionService

? ? ? ? 根據上面的介紹我們知道,現在在Java中使用多線程通常不會再使用Thread對象了。而是會用到java.util.concurrent包下的ExecutorService來初始化一個線程池供我們使用。使用ExecutorService類的時候,我們常維護一個list保存submit的callable task所返回的Future對象。然后在主線程中遍歷這個list并調用Future的get()方法取到Task的返回值。

? ? ? ?其實除了使用ExecutorService外,還可通過CompletionService包裝ExecutorService,然后調用其take()方法去取Future對象。

? ? ? ?CompletionService和ExecutorService的主要的區別在于submit的task不一定是按照加入自己維護的list順序完成的。

? ? ? ?ExecutorService中從list中遍歷的每個Future對象并不一定處于完成狀態,這時調用get()方法就會被阻塞住,如果系統是設計成每個線程完成后就能根據其結果繼續做后面的事,這樣對于處于list后面的但是先完成的線程就會增加了額外的等待時間。

? ? ? ?而CompletionService的實現是維護一個保存Future對象的BlockingQueue。只有當這個Future對象狀態是結束的時候,才會加入到這個Queue中,take()方法其實就是Producer-Consumer中的Consumer。它會從Queue中取出Future對象,如果Queue是空的,就會阻塞在那里,直到有完成的Future對象加入到Queue中。所以,先完成的必定先被取出。這樣就減少了不必要的等待時間。

?

六、使用Callable,Future返回結果

? ? ? ?Future<V>代表一個異步執行的操作,通過get()方法可以獲得操作的結果,如果異步操作還沒有完成,則,get()會使當前線程阻塞。FutureTask<V>實現了Future<V>和Runable<V>。Callable代表一個有返回值的操作。

  1. Callable<Integer>?func?=?new?Callable<Integer>(){??
  2. ????public?Integer?call()?throws?Exception?{??
  3. ????????System.out.println("inside?callable");??
  4. ????????Thread.sleep(1000);??
  5. ????????return?new?Integer(8);??
  6. ????}?????????
  7. };????????
  8. FutureTask<Integer>?futureTask??=?new?FutureTask<Integer>(func);??
  9. Thread?newThread?=?new?Thread(futureTask);??
  10. newThread.start();??
  11. ??
  12. try?{??
  13. ????System.out.println("blocking?here");??
  14. ????Integer?result?=?futureTask.get();??
  15. ????System.out.println(result);??
  16. }?catch?(InterruptedException?ignored)?{??
  17. }?catch?(ExecutionException?ignored)?{??
  18. }?

?

? ? ? ?ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor后臺線程池還沒有完成Callable的計算,則調用返回Future對象的get()方法,會阻塞直到計算完成。

? ? ? ?

? ? ? ?Java5以后可以利用Future來跟蹤異步計算的結果。在此之前主線程要想獲得工作線程(異步計算線程)的結果是比較麻煩的事情,需要我們進行特殊的程序結構設計,比較繁瑣而且容易出錯。有了Future我們就可以設計出比較優雅的異步計算程序結構模型:根據分而治之的思想,我們可以把異步計算的線程按照職責分為3類:

? ? ? 1. 異步計算的發起線程(控制線程):負責異步計算任務的分解和發起,把分解好的任務交給異步計算的work線程去執行,發起異步計算后,發起線程可以獲得Futrue的集合,從而可以跟蹤異步計算結果

? ? ? 2. 異步計算work線程:負責具體的計算任務

? ? ? 3. 異步計算結果收集線程:從發起線程那里獲得Future的集合,并負責監控Future的狀態,根據Future的狀態來處理異步計算的結果。



本文轉自農夫山泉別墅博客園博客,原文鏈接:http://www.cnblogs.com/yaowen/p/6323689.html,如需轉載請自行聯系原作者

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/286391.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/286391.shtml
英文地址,請注明出處:http://en.pswp.cn/news/286391.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言試題八之計算下列級數和,和值由函數值返回 S=1+x+x^2/2! + x^3/3!+…x^n/n!

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 計算下列級…

with管理文件操作

為了避免打開文件后忘記關閉&#xff0c;可以通過管理上下文&#xff0c;即&#xff1a; with open(log,r) as f: f.write(xxxxxx)f.readlines()...................如此方式&#xff0c;當with代碼塊執行完畢時&#xff0c;內部會自動關閉并釋放文件資源。以往我們打開…

學習SQL數據更新,這一篇就夠了!

【任務描述】 數據查詢不能改變數據庫中的數據,僅僅是把數據庫中符號條件的某些信息反饋給用戶。一個數據庫若要保持數據的正確性、及時性、則要依賴于數據庫的更新功能。數據更新主要包括插入數據、修改數據和刪除數據。 擴展閱讀:《學習SQL數據查詢,這一篇就夠了!》 文章…

網頁精美動效/動畫制作 按鈕鼠標懸浮動效的注意點 02《炫彩網頁 iVX 無代碼動效/動畫制作》

一、按鈕動效的使用 在上一節中&#xff0c;我們創建了一個動效&#xff0c;但是并沒有使用&#xff0c;在此我們給按鈕設置一個懸浮事件&#xff0c;當鼠標懸浮在按鈕之上后就調用該動效&#xff0c;點擊按鈕添加事件&#xff1a; 點擊按鈕添加事件后將會出現一個事件編輯框…

WPF 實現帶明細的環形圖表

本文經原作者授權以原創方式二次分享&#xff0c;歡迎轉載、分享。原文作者&#xff1a;普通的地球人原文地址&#xff1a;https://www.cnblogs.com/tsliwei/p/7155616.htmlGithub地址&#xff1a;https://github.com/WPFDevelopersOrg/WPFDevelopers.Charts大體思路圖表使用Ar…

SQL Server 2008 R2 安裝時提示“Reporting Services目錄數據庫文件存在”

打開MSSQL數據庫管理系統的安裝目錄&#xff0c;例如&#xff1a; X:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA。 其中 X:\是你安裝MS SQL數據庫管理系統實例所在的盤符. 刪除 X:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DA…

C語言試題九之s=(ln(1)+ln(2)+ln(3)+…+ln(m))^0.5,s作為函數值返回

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、 題目 計算:s=…

幾行代碼搞定樹形文本轉XML和JSON

由于需要將百度腦圖的內容導出為xml或者json格式&#xff0c;發現百度腦圖只能導出為樹形文本&#xff0c;所以就寫了個小應用給編輯用。/// <summary>/// 樹形文本轉xml/// </summary>/// <param name"txt"></param>/// <returns><…

2019年ESRI技術公開課(19集視頻全)

1. 視頻合集簡介 本視頻合集為2019版ESRI技術公開視頻課&#xff0c;共19集全&#xff0c;主要內容包括ArcGIS、ENVI、大數據、Python應用、大數據、點云場景、三維模型、地理建模、橢球面積、深度學習技術等。 2. 視頻合集目錄 2019年Esri技術公開課&#xff08;1&#xff09;…

VSAN見證虛擬設備

VSAN 6.1發布了也有兩三個月了&#xff0c;其中有2個比較顯著的新特性&#xff0c;一個就是支持Stretched Cluster, 也就是說你的VSAN集群現在可以不在一個物理位置了&#xff0c;可以跨數據中心部署了&#xff1b;另外一個就是2節點VSAN。我們知道&#xff0c;原來的VSAN至少需…

《iVX 高仿美團APP制作移動端完整項目》01 標題需求分析思路及制作流程

點擊整個專欄查看其它系列文章 &#xff08;系列文章更新中…&#xff09;&#xff1a;《iVX 高仿美團APP制作移動端完整項目》 項目界面預覽&#xff1a; 一、創建項目 首先打開在線編輯器地址&#xff1a;https://editor.ivx.cn/ 隨后登錄帳號后創建一個相對應用項目&…

zepto源碼研究 - ajax.js($.ajaxJSONP 的分析)

簡要&#xff1a;jsonp是一種服務器和客戶端信息傳遞方式&#xff0c;一般是利用script元素賦值src來發起請求。一般凡是帶有src屬性的元素發起的請求都是可以跨域的。 那么jsonp是如何獲取服務器的數據的呢&#xff1f; jsonp先將指定的一個函數名作為url后面的參數傳遞到服務…

C語言試題十之將兩個兩位數的正整數a b合并形成一個整數放在c中。合并的方式是:將a數的十位和個位數依次放在c的十位和千位上,b數的十位和個位數依次放在c數的個位和百位上。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、 題目 請編寫函…

Blazor University (27)路由 —— 檢測導航事件

原文鏈接&#xff1a;https://blazor-university.com/routing/detecting-navigation-events/檢測導航事件源代碼[1]從 Blazor 訪問瀏覽器導航是通過 NavigationManager 服務提供的。這可以使用 razor 文件中的 inject 或 CS 文件中的 [Inject] 屬性注入到 Blazor 組件中。Locat…

創建 overlay 網絡 - 每天5分鐘玩轉 Docker 容器技術(50)

上一節我們搭建好實驗環境&#xff0c;配置并運行了consul&#xff0c;今天開始創建 overlay 網絡。 在 host1 中創建 overlay 網絡 ov_net1&#xff1a; -d overlay 指定 driver 為 overaly。 docker network ls 查看當前網絡&#xff1a; 注意到 ov_net1 的 SCOPE 為 global&…

Js+Css 控制iframe內容自動縮放

豎屏橫屏效果<div class"h5box"> <iframe src"http://player.youku.com/embed/XMTI4MjU5OTA3Mg" frameborder"0" width"1280px" height"720px"></iframe> </div><script type"tex…

西北冬日的校園很靜謐,卻不失韻味,因為有我們美好的青春!

冬日的校園&#xff0c;從枯黃的落葉開始。。。 落葉與柵欄情深。 冬日的籃球場上&#xff0c;不乏揮汗如雨的你&#xff0c;因為你是夢想與自由的追逐者&#xff0c;你可以戰勝自己的懶惰。 我們的測量實訓場&#xff0c;英雄的用武之地。 測樁&#xff1a;測量的控制點&#…

ps、top 、free查看用戶資源信息

查看root用戶的進程信息。 運行命令&#xff1a; ps -u root 查看oracle用戶的進程信息。 運行命令&#xff1a; ps -u oracle 若查看現在的資源占用情況&#xff0c;如何呢&#xff1f; 運行命令&#xff1a; top 可以很詳細的查看各個進程的運行情況。 若查看內存使用情…

《iVX 高仿美團APP制作移動端完整項目》02 搜索、搜索提示及類別需求分析思路及制作流程

點擊整個專欄查看其它系列文章 &#xff08;系列文章更新中…&#xff09;&#xff1a;《iVX 高仿美團APP制作移動端完整項目》 項目界面預覽&#xff1a; 一、搜索制作 在上一節中我們完成了標題頭的制作&#xff0c;接下來我們查看如何制作搜索欄以及分類區制作。 首先我…

C語言試題十一之計算并輸出下列多項式值:sn=(1-1/2)+(1/3-1/4)+…+(1/(2n-1)1/2n).

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、 題目 請編寫函…