ในโหมดการใช้งาน Java เมื่อวานนี้กลไกการล็อคแบบตรวจสอบสองครั้งของเราได้แนะนำคำหลัก volatile เนื่องจากปัญหาการสั่งซื้อการสั่งซื้อใหม่ เพื่อนหลายคนถามฉันว่าทำไมฉันต้องเพิ่มคำหลักที่ volatile ? และมีผลเวทย์มนตร์อะไรบ้าง?
เกี่ยวกับคำหลัก volatile เราได้กล่าวถึงสั้น ๆ ในคำอธิบายของเมื่อวานนี้: ตัวแปรที่ใช้ร่วมกันแก้ไขโดย volatile จะมีสองแอตทริบิวต์ต่อไปนี้:
ตัวแปรที่ใช้ร่วมกัน: หากตัวแปรมีสำเนาในหน่วยความจำการทำงานของหลายเธรดตัวแปรนี้เป็นตัวแปรที่ใช้ร่วมกันของเธรดเหล่านี้
การมองเห็น: การปรับเปลี่ยนเธรดเป็นค่าตัวแปรที่ใช้ร่วมกันสามารถมองเห็นได้โดยเธรดอื่นในเวลาที่เหมาะสม
สำหรับการจัดลำดับใหม่หากคุณไม่คุ้นเคยกับ Google มันดังนั้นฉันจะไม่พูดถึงที่นี่ เพียงจำไว้ว่าเมื่อใช้งานตัวแปรที่ใช้ร่วมกันในหลายเธรดคุณต้องจำไว้ว่าต้องเพิ่มการปรับเปลี่ยนที่ผันผวน
เนื่องจากข้อ จำกัด ด้านเวลาเรายังต้องไปที่หัวข้อของวันนี้ก่อน ความผันผวนของคำหลักยังคงตรวจจับได้ง่ายในการสัมภาษณ์ที่ต้องใช้ทักษะการเขียนโปรแกรมพร้อมกัน ฉันจะอธิบายให้คุณฟังสั้น ๆ ในภายหลัง
ป้อนโหนดหัวของรายการที่เชื่อมโยงเดียวและพิมพ์ค่าของแต่ละโหนดตั้งแต่ปลายจนถึงตอนท้าย
เรามีรายการที่เชื่อมโยงมากมายรายการที่เชื่อมโยงเดี่ยวรายการสองรายการที่เชื่อมโยงสองทางรายการที่เชื่อมโยงวงแหวน ฯลฯ นี่เป็นโหมดรายการที่เชื่อมโยงเดียวที่พบบ่อยที่สุด เรามักจะจัดเก็บข้อมูลในพื้นที่จัดเก็บข้อมูลจากนั้นตัวชี้ชี้ไปที่โหนดถัดไป แม้ว่าจะไม่มีแนวคิดของตัวชี้ใน Java แต่การอ้างอิงของ Java นั้นเหมาะสมกับปัญหา
เมื่อเราเห็นคำถามนี้เรามักจะรู้อย่างรวดเร็วว่าแต่ละโหนดมีแอตทริบิวต์ถัดไปดังนั้นจึงเป็นเรื่องง่ายมากที่จะส่งออกตั้งแต่ต้นจนจบ ดังนั้นเราจะนึกถึงการใช้ลูปเป็นครั้งแรกโดยธรรมชาติเพื่อนำโหนดทั้งหมดออกมาและเก็บไว้ในอาร์เรย์จากนั้นสำรวจอาร์เรย์ตามลำดับย้อนกลับเพื่อให้ค่าโหนดของรายการที่เชื่อมโยงเดียวสามารถพิมพ์ได้ตามลำดับย้อนกลับ
เราคิดว่าข้อมูลของโหนดเป็นประเภท int รหัสการใช้งานมีดังนี้:
Public Class Test05 {โหนดระดับคงที่สาธารณะ {int data; โหนดถัดไป; } โมฆะสาธารณะคงที่ printlinkReverse (หัวโหนด) {arraylist <node> nodes = new ArrayList <> (); ในขณะที่ (หัว! = null) {nodes.add (หัว); head = head.next; } สำหรับ (int i = nodes.size ()-1; i> = 0; i--) {system.out.print (nodes.get (i) .data + ""); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {node head = new node (); head.data = 1; head.next = new node (); head.next.data = 2; head.next.next = new node (); head.next.next.data = 3; head.next.next.next.next = new node (); head.next.next.next.data = 4; head.next.next.next.next.next = new node (); head.next.next.next.data = 5; printlinkreverse (หัว); -วิธีนี้สามารถใช้การพิมพ์แบบย้อนกลับของข้อมูลรายการที่เชื่อมโยงได้ แต่เห็นได้ชัดว่าใช้สองรอบเต็มโดยมีความซับซ้อนของเวลาของ O (n²) ฯลฯ เอาต์พุตย้อนกลับ? ดูเหมือนว่ามีโครงสร้างข้อมูลที่สามารถแก้ปัญหานี้ได้อย่างสมบูรณ์แบบและโครงสร้างข้อมูลนี้เป็นสแต็ก
สแต็กเป็นโครงสร้างข้อมูล "สุดท้ายในครั้งแรก" หลักการของสแต็กสามารถตอบสนองความต้องการของเราได้ดีขึ้นดังนั้นรหัสการใช้งานมีดังนี้:
Public Class Test05 {โหนดระดับคงที่สาธารณะ {int data; โหนดถัดไป; } โมฆะคงที่สาธารณะ printlinkReverse (หัวโหนด) {สแต็ก <node> stack = สแต็กใหม่ <> (); ในขณะที่ (หัว! = null) {stack.push (หัว); head = head.next; } ในขณะที่ (! stack.isempty ()) {system.out.print (stack.pop (). data + ""); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {node head = new node (); head.data = 1; head.next = new node (); head.next.data = 2; head.next.next = new node (); head.next.next.data = 3; head.next.next.next.next = new node (); head.next.next.next.data = 4; head.next.next.next.next.next = new node (); head.next.next.next.next.data = 5; printlinkreverse (หัว); -เนื่องจากมันสามารถนำไปใช้โดยใช้สแต็กจึงเป็นเรื่องง่ายมากที่เราจะคิดว่าการเรียกซ้ำสามารถแก้ปัญหานี้ได้เนื่องจากการเรียกซ้ำเป็นโครงสร้างสแต็กเป็นหลัก ในการใช้รายการลิงก์เอาต์พุตตามลำดับย้อนกลับทุกครั้งที่เราเข้าถึงโหนดเราจะส่งออกโหนดที่อยู่ด้านหลังซ้ำแล้วซ้ำอีกแล้วเอาต์พุตโหนดเอง ด้วยวิธีนี้ผลลัพธ์ผลลัพธ์ของรายการที่เชื่อมโยงจะกลับด้านตามธรรมชาติ
รหัสมีดังนี้:
Public Class Test05 {โหนดระดับคงที่สาธารณะ {int data; โหนดถัดไป; } โมฆะคงที่สาธารณะ printLinkReverse (หัวโหนด) {ถ้า (หัว! = null) {printlinkReverse (head.next); System.out.print (head.data+""); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {node head = new node (); head.data = 1; head.next = new node (); head.next.data = 2; head.next.next = new node (); head.next.next.data = 3; head.next.next.next = new node (); head.next.next.next.data = 4; head.next.next.next.next.next.next = new node (); head.next.next.next.next.data = 5; printlinkreverse (หัว); - แม้ว่ารหัสซ้ำจะดูเรียบร้อยมาก แต่ก็มีปัญหา: เมื่อรายการที่เชื่อมโยงยาวมากมันจะนำไปสู่การโทรระดับลึกอย่างแน่นอนซึ่งอาจทำให้ฟังก์ชั่นเรียกสแต็กล้น ดังนั้นรหัสที่แสดงรหัสตามลูปนั้นแข็งแกร่งกว่า
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น