อินสแตนซ์ Java 8 Stream ควรจะปิด () เสมอหรือไม่


12

Quad the Javadoc :

สตรีมมีเมธอด BaseStream.close () และใช้ AutoCloseable แต่อินสแตนซ์สตรีมเกือบทั้งหมดไม่จำเป็นต้องปิดจริงหลังการใช้งาน โดยทั่วไปเฉพาะสตรีมที่มีแหล่งที่มาเป็นแชนเนล IO (เช่นที่ส่งคืนโดย Files.lines (Path, Charset)) เท่านั้นที่จะต้องปิด สตรีมส่วนใหญ่ได้รับการสนับสนุนโดยคอลเลกชันอาร์เรย์หรือการสร้างฟังก์ชั่นซึ่งไม่จำเป็นต้องมีการจัดการทรัพยากรพิเศษ (หากกระแสต้องปิดก็สามารถประกาศเป็นทรัพยากรในงบลองกับทรัพยากร)

"เกือบทั้งหมด" และ "โดยทั่วไป" นั้นคลุมเครือ - ถ้าคุณกำลังเขียนไลบรารีและคุณกำลังสรุปแหล่งที่มาของสตรีมของคุณจากผู้ใช้สตรีมนั้นคุณต้องถามตัวเองเสมอ - "ฉันควรปิดหรือไม่ นี้?" IO-ได้รับการสนับสนุนสตรีมจะต้องมีการปิดเพราะการดำเนินงานสถานีไม่ได้เรียกcloseเพื่อให้ได้อย่างมีประสิทธิภาพฉันมักจะมีทั้งจำ / เอกสารที่สตรีมของฉันมาจากหรือฉันมักจะต้องcloseมัน

ตัวเลือกนิวเคลียร์ที่ฉันคิดว่าน่าจะไม่ส่งคืนสตรีมจากวิธีการหรือยอมรับพารามิเตอร์สตรีมซึ่งเป็นความเชื่อมั่นที่บางคนสะท้อนในทีม JDK ฉันพบว่ามัน จำกัด มากเกินไปเมื่อพิจารณาถึงประโยชน์ในทางปฏิบัติของสตรีม

อะไรคือวิธีปฏิบัติที่ดีที่สุดของคุณเกี่ยวกับการปิดสายธาร ฉันดูออนไลน์เพื่อหาคำตอบสำหรับเรื่องนี้จากบางคนของ JDK ที่มักจะใช้งานกับคำถามชุมชนที่คล้ายกัน แต่ไม่พบสิ่งใดที่เกี่ยวข้อง


ไม่ใช่นักพัฒนา Java แต่ฉันจะใช้กฎเหล่านี้: - หากมีการส่งกระแสข้อมูลเป็นอาร์กิวเมนต์ให้เอกสารที่ผู้เรียกต้องปิดกระแสหากจำเป็น - หากกระแสข้อมูลถูกส่งคืนให้คุณจากฟังก์ชั่นสมมติว่าคุณต้องปิดมัน
Bart van Ingen Schenau

คำตอบ:


6

ดังที่คุณกล่าวใน Java คุณจำเป็นต้องรู้อย่างแน่นอนว่าใครเป็นผู้รับผิดชอบในการปลดปล่อยทรัพยากรใดเพื่อให้คุณสามารถวางโครงสร้างการดักจับที่เหมาะสมลองกับทรัพยากรหรือมอบหมายงานนั้น

สิ่งเดียวที่คุณสามารถพึ่งพา GC ในการทำความสะอาดสำหรับคุณคือหน่วยความจำบริสุทธิ์ 100%
หากอาจมีแหล่งข้อมูลอื่นผสมอยู่สิ่งเดียวที่คุณทำได้อย่างสมเหตุสมผลก็คือเล่นปลอดภัย


ดังนั้นโดยทั่วไปcloseเป็นทางเลือกที่ปลอดภัยเท่านั้น? ฉันเดาว่าคำถามคือจะไม่ทำให้โค้ดดูน่าเกลียดเกินไปทุกครั้งที่สตรีมจะมีประโยชน์ในการใช้งาน
RuslanD

1
ใช่ถ้ามีอาจจะเป็นทรัพยากรที่ไม่หน่วยความจำ, สิ่งที่ปลอดภัยเท่านั้นที่จะทำคือถือว่ามีอยู่ ไม่มีทางที่จะถึงแม้ว่า Java จะไม่เหมาะสำหรับทรัพยากรที่ไม่ใช่ GC'd
Deduplicator

ดังนั้นถ้ามันเป็นแค่กระแสระหว่างสองคอลเลกชัน (หน่วยความจำบริสุทธิ์) การปิดมันไม่จำเป็นเลยเหรอ?
Amalgovinus

@Amalgovinus ถูกต้อง
Brad Cupit

5

เท่าที่เป็นไปได้ "แนวปฏิบัติที่ดีที่สุด" ฉันคิดว่าเป็นความคิดที่ดีที่จะใช้หลักการตั้งชื่อสำหรับวิธีการที่ส่งคืน "ทรัพยากรสตรีม"

หากกระแสจะต้องมีการclose()เอ็ดเรียกวิธีโรงงานหรือopen() openStream()วิธีการโทรที่สร้างกระแสชั่วคราวstream()หลังจากการประชุมที่จัดตั้งขึ้นโดย SDK วาง javadoc ไว้บนเมธอดเพื่อแจ้งเตือนไคลเอ็นต์เสมอว่าไคลเอ็นต์ต้องclose()ใช้

public interface StreamingServer<RECORD> {
    /** 
     * Return a memory-efficient record stream from {@code source}.
     * Clients <em>must</em> call {@link Stream#close} to dispose the
     * stream.
     */
    Stream<RECORD> openStream(URI source) throws IOException;
}

ฉันหวังว่าผู้เขียน SDK ไม่ได้เลือกที่จะใส่AutoCloseableคลาสสตรีมพื้นฐาน ResourceStreamประเภทย่อยที่แตกต่างซึ่งนำไปปฏิบัติเล็กน้อยAutoCloseableจะทำให้สัญญาต่าง ๆ ชัดเจน จากนั้นคุณไม่สามารถปิดสิ่งStreamที่ไม่ต้องการได้และคุณสามารถตรวจพบการจัดการที่ผิดพลาดResourceStreamในเครื่องมือวิเคราะห์แบบคงที่

ขึ้นอยู่กับความต้องการของ codebase ของคุณ (และความสามารถของคุณในการบังคับใช้ข้อตกลงในการตรวจสอบโค้ด) คุณสามารถสร้างคลาสย่อยสตรีมที่ต้องการปิดได้ด้วยตัวเอง หรือถ้าคุณต้องการสร้างเครื่องมือวิเคราะห์แบบคงที่ของคุณเองคำอธิบายประกอบวิธีการที่ทำเครื่องหมายทรัพยากรที่มีการจัดการโดยตรง

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.