日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

10分钟看懂, Java NIO 底层原理

發(fā)布時間:2025/3/20 java 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10分钟看懂, Java NIO 底层原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊上方?好好學java?,選擇?星標?公眾號

重磅資訊、干貨,第一時間送達

今日推薦:硬剛一周,3W字總結(jié),一年的經(jīng)驗告訴你如何準備校招!

個人原創(chuàng)100W+訪問量博客:點擊前往,查看更多

寫在前面

很多的小伙伴,被java IO 模型,搞得有點兒暈,一會兒是4種模型,一會兒又變成了5種模型。

很多的小伙伴,也被nio這個名詞搞暈了,一會兒java 的nio 不叫 非阻塞io,一會兒java nio 又是非阻塞io,到底是啥呢?

很多的小伙伴,被異步和非阻塞搞暈了。都非阻塞了,難道不是異步的嗎?這這,好難呀。

此文,從底層入手,給各位小伙伴,起底一下,java的四大io模型。需要面試的,或者沒有弄清楚的小伙伴,徹底的有福了。

1.1. Java IO讀寫原理

無論是Socket的讀寫還是文件的讀寫,在Java層面的應用開發(fā)或者是linux系統(tǒng)底層開發(fā),都屬于輸入input和輸出output的處理,簡稱為IO讀寫。在原理上和處理流程上,都是一致的。區(qū)別在于參數(shù)的不同。

用戶程序進行IO的讀寫,基本上會用到read&write兩大系統(tǒng)調(diào)用??赡懿煌僮飨到y(tǒng),名稱不完全一樣,但是功能是一樣的。

先強調(diào)一個基礎(chǔ)知識:read系統(tǒng)調(diào)用,并不是把數(shù)據(jù)直接從物理設(shè)備,讀數(shù)據(jù)到內(nèi)存。write系統(tǒng)調(diào)用,也不是直接把數(shù)據(jù),寫入到物理設(shè)備。

read系統(tǒng)調(diào)用,是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到進程緩沖區(qū);而write系統(tǒng)調(diào)用,是把數(shù)據(jù)從進程緩沖區(qū)復制到內(nèi)核緩沖區(qū)。這個兩個系統(tǒng)調(diào)用,都不負責數(shù)據(jù)在內(nèi)核緩沖區(qū)和磁盤之間的交換。底層的讀寫交換,是由操作系統(tǒng)kernel內(nèi)核完成的。

1.1.1. 內(nèi)核緩沖與進程緩沖區(qū)

緩沖區(qū)的目的,是為了減少頻繁的系統(tǒng)IO調(diào)用。大家都知道,系統(tǒng)調(diào)用需要保存之前的進程數(shù)據(jù)和狀態(tài)等信息,而結(jié)束調(diào)用之后回來還需要恢復之前的信息,為了減少這種損耗時間、也損耗性能的系統(tǒng)調(diào)用,于是出現(xiàn)了緩沖區(qū)。

有了緩沖區(qū),操作系統(tǒng)使用read函數(shù)把數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到進程緩沖區(qū),write把數(shù)據(jù)從進程緩沖區(qū)復制到內(nèi)核緩沖區(qū)中。等待緩沖區(qū)達到一定數(shù)量的時候,再進行IO的調(diào)用,提升性能。至于什么時候讀取和存儲則由內(nèi)核來決定,用戶程序不需要關(guān)心。

在linux系統(tǒng)中,系統(tǒng)內(nèi)核也有個緩沖區(qū)叫做內(nèi)核緩沖區(qū)。每個進程有自己獨立的緩沖區(qū),叫做進程緩沖區(qū)。

所以,用戶程序的IO讀寫程序,大多數(shù)情況下,并沒有進行實際的IO操作,而是在讀寫自己的進程緩沖區(qū)。

1.1.2. java IO讀寫的底層流程

用戶程序進行IO的讀寫,基本上會用到系統(tǒng)調(diào)用read&write,read把數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到進程緩沖區(qū),write把數(shù)據(jù)從進程緩沖區(qū)復制到內(nèi)核緩沖區(qū),它們不等價于數(shù)據(jù)在內(nèi)核緩沖區(qū)和磁盤之間的交換。

在這里插入圖片描述

首先看看一個典型Java 服務端處理網(wǎng)絡(luò)請求的典型過程:

(1)客戶端請求

Linux通過網(wǎng)卡,讀取客戶斷的請求數(shù)據(jù),將數(shù)據(jù)讀取到內(nèi)核緩沖區(qū)。

(2)獲取請求數(shù)據(jù)

服務器從內(nèi)核緩沖區(qū)讀取數(shù)據(jù)到Java進程緩沖區(qū)。

(1)服務器端業(yè)務處理

Java服務端在自己的用戶空間中,處理客戶端的請求。

(2)服務器端返回數(shù)據(jù)

Java服務端已構(gòu)建好的響應,從用戶緩沖區(qū)寫入系統(tǒng)緩沖區(qū)。

(3)發(fā)送給客戶端

Linux內(nèi)核通過網(wǎng)絡(luò) I/O ,將內(nèi)核緩沖區(qū)中的數(shù)據(jù),寫入網(wǎng)卡,網(wǎng)卡通過底層的通訊協(xié)議,會將數(shù)據(jù)發(fā)送給目標客戶端。

1.2. 四種主要的IO模型

服務器端編程經(jīng)常需要構(gòu)造高性能的IO模型,常見的IO模型有四種:

(1)同步阻塞IO(Blocking IO)

首先,解釋一下這里的阻塞與非阻塞:

阻塞IO,指的是需要內(nèi)核IO操作徹底完成后,才返回到用戶空間,執(zhí)行用戶的操作。阻塞指的是用戶空間程序的執(zhí)行狀態(tài),用戶空間程序需等到IO操作徹底完成。傳統(tǒng)的IO模型都是同步阻塞IO。在java中,默認創(chuàng)建的socket都是阻塞的。

其次,解釋一下同步與異步

同步IO,是一種用戶空間與內(nèi)核空間的調(diào)用發(fā)起方式。同步IO是指用戶空間線程是主動發(fā)起IO請求的一方,內(nèi)核空間是被動接受方。異步IO則反過來,是指內(nèi)核kernel是主動發(fā)起IO請求的一方,用戶線程是被動接受方。

(2)同步非阻塞IO(Non-blocking IO)

非阻塞IO,指的是用戶程序不需要等待內(nèi)核IO操作完成后,內(nèi)核立即返回給用戶一個狀態(tài)值,用戶空間無需等到內(nèi)核的IO操作徹底完成,可以立即返回用戶空間,執(zhí)行用戶的操作,處于非阻塞的狀態(tài)。

簡單的說:阻塞是指用戶空間(調(diào)用線程)一直在等待,而且別的事情什么都不做;非阻塞是指用戶空間(調(diào)用線程)拿到狀態(tài)就返回,IO操作可以干就干,不可以干,就去干的事情。

非阻塞IO要求socket被設(shè)置為NONBLOCK。

強調(diào)一下,這里所說的NIO(同步非阻塞IO)模型,并非Java的NIO(New IO)庫。

(3)IO多路復用(IO Multiplexing)

即經(jīng)典的Reactor設(shè)計模式,有時也稱為異步阻塞IO,Java中的Selector和Linux中的epoll都是這種模型。

(4)異步IO(Asynchronous IO)

異步IO,指的是用戶空間與內(nèi)核空間的調(diào)用方式反過來。用戶空間線程是變成被動接受的,內(nèi)核空間是主動調(diào)用者。

這一點,有點類似于Java中比較典型的模式是回調(diào)模式,用戶空間線程向內(nèi)核空間注冊各種IO事件的回調(diào)函數(shù),由內(nèi)核去主動調(diào)用。

1.3. 同步阻塞IO(Blocking IO)

在linux中的Java進程中,默認情況下所有的socket都是blocking IO。在阻塞式 I/O 模型中,應用程序在從IO系統(tǒng)調(diào)用開始,一直到到系統(tǒng)調(diào)用返回,這段時間是阻塞的。返回成功后,應用進程開始處理用戶空間的緩存數(shù)據(jù)。

在這里插入圖片描述

舉個栗子,發(fā)起一個blocking socket的read讀操作系統(tǒng)調(diào)用,流程大概是這樣:

(1)當用戶線程調(diào)用了read系統(tǒng)調(diào)用,內(nèi)核(kernel)就開始了IO的第一個階段:準備數(shù)據(jù)。很多時候,數(shù)據(jù)在一開始還沒有到達(比如,還沒有收到一個完整的Socket數(shù)據(jù)包),這個時候kernel就要等待足夠的數(shù)據(jù)到來。

(2)當kernel一直等到數(shù)據(jù)準備好了,它就會將數(shù)據(jù)從kernel內(nèi)核緩沖區(qū),拷貝到用戶緩沖區(qū)(用戶內(nèi)存),然后kernel返回結(jié)果。

(3)從開始IO讀的read系統(tǒng)調(diào)用開始,用戶線程就進入阻塞狀態(tài)。一直到kernel返回結(jié)果后,用戶線程才解除block的狀態(tài),重新運行起來。

所以,blocking IO的特點就是在內(nèi)核進行IO執(zhí)行的兩個階段,用戶線程都被block了。

BIO的優(yōu)點:

程序簡單,在阻塞等待數(shù)據(jù)期間,用戶線程掛起。用戶線程基本不會占用 CPU 資源。

BIO的缺點:

一般情況下,會為每個連接配套一條獨立的線程,或者說一條線程維護一個連接成功的IO流的讀寫。在并發(fā)量小的情況下,這個沒有什么問題。但是,當在高并發(fā)的場景下,需要大量的線程來維護大量的網(wǎng)絡(luò)連接,內(nèi)存、線程切換開銷會非常巨大。因此,基本上,BIO模型在高并發(fā)場景下是不可用的。

1.4. 同步非阻塞NIO(None Blocking IO)

在linux系統(tǒng)下,可以通過設(shè)置socket使其變?yōu)閚on-blocking。NIO 模型中應用程序在一旦開始IO系統(tǒng)調(diào)用,會出現(xiàn)以下兩種情況:

(1)在內(nèi)核緩沖區(qū)沒有數(shù)據(jù)的情況下,系統(tǒng)調(diào)用會立即返回,返回一個調(diào)用失敗的信息。

(2)在內(nèi)核緩沖區(qū)有數(shù)據(jù)的情況下,是阻塞的,直到數(shù)據(jù)從內(nèi)核緩沖復制到用戶進程緩沖。復制完成后,系統(tǒng)調(diào)用返回成功,應用進程開始處理用戶空間的緩存數(shù)據(jù)。

在這里插入圖片描述

舉個栗子。發(fā)起一個non-blocking socket的read讀操作系統(tǒng)調(diào)用,流程是這個樣子:

(1)在內(nèi)核數(shù)據(jù)沒有準備好的階段,用戶線程發(fā)起IO請求時,立即返回。用戶線程需要不斷地發(fā)起IO系統(tǒng)調(diào)用。

(2)內(nèi)核數(shù)據(jù)到達后,用戶線程發(fā)起系統(tǒng)調(diào)用,用戶線程阻塞。內(nèi)核開始復制數(shù)據(jù)。它就會將數(shù)據(jù)從kernel內(nèi)核緩沖區(qū),拷貝到用戶緩沖區(qū)(用戶內(nèi)存),然后kernel返回結(jié)果。

(3)用戶線程才解除block的狀態(tài),重新運行起來。經(jīng)過多次的嘗試,用戶線程終于真正讀取到數(shù)據(jù),繼續(xù)執(zhí)行。

NIO的特點:

應用程序的線程需要不斷的進行 I/O 系統(tǒng)調(diào)用,輪詢數(shù)據(jù)是否已經(jīng)準備好,如果沒有準備好,繼續(xù)輪詢,直到完成系統(tǒng)調(diào)用為止。

NIO的優(yōu)點:

每次發(fā)起的 IO 系統(tǒng)調(diào)用,在內(nèi)核的等待數(shù)據(jù)過程中可以立即返回。用戶線程不會阻塞,實時性較好。

NIO的缺點:

需要不斷的重復發(fā)起IO系統(tǒng)調(diào)用,這種不斷的輪詢,將會不斷地詢問內(nèi)核,這將占用大量的 CPU 時間,系統(tǒng)資源利用率較低。

總之,NIO模型在高并發(fā)場景下,也是不可用的。一般 Web 服務器不使用這種 IO 模型。一般很少直接使用這種模型,而是在其他IO模型中使用非阻塞IO這一特性。java的實際開發(fā)中,也不會涉及這種IO模型。

再次說明,Java NIO(New IO) 不是IO模型中的NIO模型,而是另外的一種模型,叫做IO多路復用模型( IO multiplexing )。

1.5. IO多路復用模型(I/O multiplexing)

如何避免同步非阻塞NIO模型中輪詢等待的問題呢?這就是IO多路復用模型。

IO多路復用模型,就是通過一種新的系統(tǒng)調(diào)用,一個進程可以監(jiān)視多個文件描述符,一旦某個描述符就緒(一般是內(nèi)核緩沖區(qū)可讀/可寫),內(nèi)核kernel能夠通知程序進行相應的IO系統(tǒng)調(diào)用。

目前支持IO多路復用的系統(tǒng)調(diào)用,有 select,epoll等等。select系統(tǒng)調(diào)用,是目前幾乎在所有的操作系統(tǒng)上都有支持,具有良好跨平臺特性。epoll是在linux 2.6內(nèi)核中提出的,是select系統(tǒng)調(diào)用的linux增強版本。

IO多路復用模型的基本原理就是select/epoll系統(tǒng)調(diào)用,單個線程不斷的輪詢select/epoll系統(tǒng)調(diào)用所負責的成百上千的socket連接,當某個或者某些socket網(wǎng)絡(luò)連接有數(shù)據(jù)到達了,就返回這些可以讀寫的連接。因此,好處也就顯而易見了——通過一次select/epoll系統(tǒng)調(diào)用,就查詢到到可以讀寫的一個甚至是成百上千的網(wǎng)絡(luò)連接。

舉個栗子。發(fā)起一個多路復用IO的的read讀操作系統(tǒng)調(diào)用,流程是這個樣子:

在這里插入圖片描述

在這種模式中,首先不是進行read系統(tǒng)調(diào)動,而是進行select/epoll系統(tǒng)調(diào)用。當然,這里有一個前提,需要將目標網(wǎng)絡(luò)連接,提前注冊到select/epoll的可查詢socket列表中。然后,才可以開啟整個的IO多路復用模型的讀流程。

(1)進行select/epoll系統(tǒng)調(diào)用,查詢可以讀的連接。kernel會查詢所有select的可查詢socket列表,當任何一個socket中的數(shù)據(jù)準備好了,select就會返回。

當用戶進程調(diào)用了select,那么整個線程會被block(阻塞掉)。

(2)用戶線程獲得了目標連接后,發(fā)起read系統(tǒng)調(diào)用,用戶線程阻塞。內(nèi)核開始復制數(shù)據(jù)。它就會將數(shù)據(jù)從kernel內(nèi)核緩沖區(qū),拷貝到用戶緩沖區(qū)(用戶內(nèi)存),然后kernel返回結(jié)果。

(3)用戶線程才解除block的狀態(tài),用戶線程終于真正讀取到數(shù)據(jù),繼續(xù)執(zhí)行。

多路復用IO的特點:

IO多路復用模型,建立在操作系統(tǒng)kernel內(nèi)核能夠提供的多路分離系統(tǒng)調(diào)用select/epoll基礎(chǔ)之上的。多路復用IO需要用到兩個系統(tǒng)調(diào)用(system call), 一個select/epoll查詢調(diào)用,一個是IO的讀取調(diào)用。

和NIO模型相似,多路復用IO需要輪詢。負責select/epoll查詢調(diào)用的線程,需要不斷的進行select/epoll輪詢,查找出可以進行IO操作的連接。

另外,多路復用IO模型與前面的NIO模型,是有關(guān)系的。對于每一個可以查詢的socket,一般都設(shè)置成為non-blocking模型。只是這一點,對于用戶程序是透明的(不感知)。

多路復用IO的優(yōu)點:

用select/epoll的優(yōu)勢在于,它可以同時處理成千上萬個連接(connection)。與一條線程維護一個連接相比,I/O多路復用技術(shù)的最大優(yōu)勢是:系統(tǒng)不必創(chuàng)建線程,也不必維護這些線程,從而大大減小了系統(tǒng)的開銷。

Java的NIO(new IO)技術(shù),使用的就是IO多路復用模型。在linux系統(tǒng)上,使用的是epoll系統(tǒng)調(diào)用。

多路復用IO的缺點:

本質(zhì)上,select/epoll系統(tǒng)調(diào)用,屬于同步IO,也是阻塞IO。都需要在讀寫事件就緒后,自己負責進行讀寫,也就是說這個讀寫過程是阻塞的。

如何充分的解除線程的阻塞呢?那就是異步IO模型。

1.6. 異步IO模型(asynchronous IO)

如何進一步提升效率,解除最后一點阻塞呢?這就是異步IO模型,全稱asynchronous I/O,簡稱為AIO。

AIO的基本流程是:用戶線程通過系統(tǒng)調(diào)用,告知kernel內(nèi)核啟動某個IO操作,用戶線程返回。kernel內(nèi)核在整個IO操作(包括數(shù)據(jù)準備、數(shù)據(jù)復制)完成后,通知用戶程序,用戶執(zhí)行后續(xù)的業(yè)務操作。

kernel的數(shù)據(jù)準備是將數(shù)據(jù)從網(wǎng)絡(luò)物理設(shè)備(網(wǎng)卡)讀取到內(nèi)核緩沖區(qū);kernel的數(shù)據(jù)復制是將數(shù)據(jù)從內(nèi)核緩沖區(qū)拷貝到用戶程序空間的緩沖區(qū)。

在這里插入圖片描述

(1)當用戶線程調(diào)用了read系統(tǒng)調(diào)用,立刻就可以開始去做其它的事,用戶線程不阻塞。

(2)內(nèi)核(kernel)就開始了IO的第一個階段:準備數(shù)據(jù)。當kernel一直等到數(shù)據(jù)準備好了,它就會將數(shù)據(jù)從kernel內(nèi)核緩沖區(qū),拷貝到用戶緩沖區(qū)(用戶內(nèi)存)。

(3)kernel會給用戶線程發(fā)送一個信號(signal),或者回調(diào)用戶線程注冊的回調(diào)接口,告訴用戶線程read操作完成了。

(4)用戶線程讀取用戶緩沖區(qū)的數(shù)據(jù),完成后續(xù)的業(yè)務操作。

異步IO模型的特點:

在內(nèi)核kernel的等待數(shù)據(jù)和復制數(shù)據(jù)的兩個階段,用戶線程都不是block(阻塞)的。用戶線程需要接受kernel的IO操作完成的事件,或者說注冊IO操作完成的回調(diào)函數(shù),到操作系統(tǒng)的內(nèi)核。所以說,異步IO有的時候,也叫做信號驅(qū)動 IO 。

異步IO模型缺點:

需要完成事件的注冊與傳遞,這里邊需要底層操作系統(tǒng)提供大量的支持,去做大量的工作。

目前來說, Windows 系統(tǒng)下通過 IOCP 實現(xiàn)了真正的異步 I/O。但是,就目前的業(yè)界形式來說,Windows 系統(tǒng),很少作為百萬級以上或者說高并發(fā)應用的服務器操作系統(tǒng)來使用。

而在 Linux 系統(tǒng)下,異步IO模型在2.6版本才引入,目前并不完善。所以,這也是在 Linux 下,實現(xiàn)高并發(fā)網(wǎng)絡(luò)編程時都是以 IO 復用模型模式為主。

小結(jié)一下:

四種IO模型,理論上越往后,阻塞越少,效率也是最優(yōu)。在這四種 I/O 模型中,前三種屬于同步 I/O,因為其中真正的 I/O 操作將阻塞線程。只有最后一種,才是真正的異步 I/O 模型,可惜目前Linux 操作系統(tǒng)尚欠完善。

推薦文章
  • 硬剛一周,3W字總結(jié),一年的經(jīng)驗告訴你如何準備校招!

  • 今年的校招,Java 好拿 offer 嗎?

  • 10月了,該聊聊今年秋招了!

  • 聊聊在騰訊實習快一個月的感受

原創(chuàng)電子書歷時整整一年總結(jié)的?Java 面試 + Java 后端技術(shù)學習指南,這是本人這幾年及校招的總結(jié),各種高頻面試題已經(jīng)全部進行總結(jié),按照章節(jié)復習即可,已經(jīng)拿到了大廠offer。 原創(chuàng)思維導圖掃碼或者微信搜?程序員的技術(shù)圈子?回復?面試?領(lǐng)取原創(chuàng)電子書和思維導圖。

總結(jié)

以上是生活随笔為你收集整理的10分钟看懂, Java NIO 底层原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产伦精品一区二区三 | 久久久久亚洲av成人人电影 | 国产精品xxx视频 | 国产网红女主播精品视频 | 国产又黄又猛又粗 | 成人激情自拍 | 欧美精品乱码视频一二专区 | 日日骑夜夜操 | 午夜时刻免费入口 | mm1313亚洲精品| 国产成人网 | 用力挺进新婚白嫩少妇 | 午夜福利电影一区二区 | 日韩黄色网址 | 爱吃波客今天最新视频 | 日日撸夜夜操 | 依依成人在线视频 | 美女在线免费视频 | 嫩草影院一区二区三区 | 私人网站 | 妻色成人网| 欧美情侣性视频 | 国产伦精品一区二区三区免费 | 黄色片网站在线看 | 黄色国产一区二区 | 天天干天天爽天天射 | 久热色| 茄子爱啪啪 | 日本特黄特黄刺激大片 | 国产精品成人无码免费 | 欧美性区 | 中文字幕一区二区三区人妻在线视频 | 国产麻豆精品久久一二三 | 五月天av影院 | 国产传媒欧美日韩 | 日韩三级国产精品 | 欧美极品少妇xxxxⅹ免费视频 | 成人一级影视 | 舔花蒂| 午夜视频在线免费看 | 亚洲女人18毛片水真多 | 国产精品传媒 | 国产色一区 | 欧美视频成人 | 欧美久久久久 | 国产又粗又长 | 亚洲AV无码久久精品浪潮 | 夏晴子在线 | 日本a在线天堂 | 日日爽视频 | 四虎最新站名点击进入 | 色天天av| 亚洲成人网页 | 999午夜 | 99re6在线观看 | 黄色一级片. | 亚洲国产精品国自产拍av | 免费不卡av在线 | 越南毛茸茸的少妇 | 粉嫩在线 | 亚洲影院在线 | av在线播放不卡 | 制服丝袜中文字幕在线 | 日本成人片网站 | 日韩国产欧美一区二区 | 青青草原av在线 | 国产福利在线视频 | 国内精品二区 | 澳门黄色| 国产一级片毛片 | 九色视频网站 | 欧美一级二级在线观看 | 美日韩精品视频 | 亚洲第一免费播放区 | 欧美日韩国产精品一区二区三区 | 久久一区二区视频 | av天天射 | 欧美sm凌虐视频网站 | 国产福利一区二区视频 | 亚洲精品99| 特级淫片aaaaaaa级附近的 | 久操不卡 | 国产主播一区二区 | 性生活视频软件 | 国产日韩欧美一区二区东京热 | 国产精品视频免费 | 亚洲大片在线观看 | 久草手机在线观看 | 国产精品美女主播 | 欧美一区二区三区成人 | 欧美7777 | 欧美日韩视频在线播放 | 人妻体内射精一区二区 | 免费看国产黄色片 | 国产碰碰| 精品区一区二区 | 久久精品国产亚洲AV成人婷婷 | 日韩www视频 | 午夜精品福利一区二区三区蜜桃 |