เจาะลึก Java ThreadLocal
ที่มา: Devgenios วันนี้คุณจะได้เรียนรู้เกี่ยวกับ ThreadLocal ซึ่งเป็นหนึ่งในคลาสทั่วไปที่ใช้ในการพัฒนาแอปพลิเคชัน Java
ThreadLocal คืออะไร
คลาสThreadLocalเก็บตัวแปรท้องถิ่นสำหรับเธรด ตัวแปรเหล่านี้ถูกแยกออกจากเธรดต่างๆ และสามารถเข้าถึงได้โดยเธรดของตัวเองเท่านั้น กรณีการใช้งานสำหรับThreadLocal :- แยกข้อมูลระหว่างเธรด
- การจัดการเซสชันสำหรับการเชื่อมต่อฐานข้อมูล
- การจัดเก็บข้อมูลการทำธุรกรรมของเธรด
วิธีใช้ ThreadLocal
ลองดูตัวอย่างง่ายๆpublic static void main(String[] args) {
//Создаем ThreadLocal
ThreadLocal<String> local = new ThreadLocal<>();
//Создаем новый класс Random
Random random = new Random();
//Создаем 5 потоков
IntStream.range(0, 5).forEach(a-> new Thread(()-> {
//Присваиваем meaning каждому потоку
local.set(a+" "+random.nextInt(100));
System.out.println("Thread number and its local value "+ local.get());
}).start());
}
ในโค้ดข้างต้น เราสร้าง คลาส ThreadLocalสร้าง 5 เธรด กำหนดค่าให้กับThreadLocalในแต่ละเธรดและพิมพ์ เมื่อส่งออกเราได้รับ: 
อะไรอยู่ภายใต้ประทุน?
หากคุณมองอย่างใกล้ชิด คุณจะเห็นว่ามีสองวิธีที่สำคัญ ใน ThreadLocal จากตัวอย่างโค้ดนี้-
สาธารณะ T รับ () {}
-
ชุดโมฆะสาธารณะ (ค่า T) {}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
เมธอดsetterจะได้รับเธรดปัจจุบันก่อน และเรียกใช้ เมธอด getMap ( )เพื่อรับ คลาส ThreadLocalMap หาก มี แผนที่อยู่ ให้นำสตรีมปัจจุบันtเป็นคีย์ พารามิเตอร์อินพุตเป็นค่า และตั้งค่า คู่ {key:value}เพื่อแมป ถ้าไม่เช่นนั้น ให้สร้างแผนที่ ตอนนี้คุณอาจมีคำถาม - ThreadLocalMap คือ อะไร
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
ThreadLocalMapเป็นคลาสคงที่ภายในในThreadLocalที่กำหนด คลาส รายการเพื่อจัดเก็บข้อมูล รายการใช้ อินสแตนซ์ ThreadLocalเป็นคีย์และตั้งค่าที่เราส่งผ่าน หากสิ่งนี้ฟังดูน่าสับสนเกินไป ณ จุดนี้ เพียงจำไว้ว่าคลาสEntryในThreadLocalMapทำหน้าที่จัดเก็บค่าจริง ในการรับข้อมูลจากThreadLocalเราใช้ วิธี getter :
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ใน เมธอด getterเราจะใช้currentThreadเป็นคีย์เพื่อรับThreadLocalMap จากนั้นแมปจะgetEntry()ตาม อินสแตนซ์ ThreadLocalและส่งคืนอินสแตน ซ์รายการ จากนั้นตามด้วยค่าที่เก็บไว้ ต่อไปนี้เป็นแผนภาพที่จะช่วยให้คุณเข้าใจได้: 

-
แต่ละเธรดจะรักษาการอ้างอิงถึงThreadLocalMap
-
ThreadLocalMapเป็นคลาสคงที่ภายในของThreadLocalและใช้ คลาส Entryสำหรับการจัดเก็บ
-
คีย์ThreadLocalMapเป็นอินสแตนซ์ของThreadLocalและสามารถมีได้หลายThreadLocals
-
ThreadLocalเองไม่ได้เก็บค่า แต่เป็นคีย์สำหรับเธรดที่จะช่วยรับค่าจากThreadLocalMap
คลาสสแกนเนอร์ใน Java
แหล่งที่มา: สื่อ โพสต์นี้จะช่วยให้คุณคุ้นเคยกับคลาส Scanner ใน Java
Scanner scan=new Scanner(System.in);
ตอนนี้เรามีวัตถุสแกนเนอร์แล้ว ออบเจ็กต์ นี้จะมีคุณสมบัติ Scanner จาก คลาส Scanner หลังจากขั้นตอนแรกผู้ใช้สามารถป้อนค่าที่ต้องการได้แล้ว แต่หากเราไม่แนะนำผู้ใช้และแสดงค่าในคอนโซลหรือในแอปพลิเคชันก็จะไม่ค่อยดีนักในแง่ของการใช้งาน ดังนั้นจึงเป็นการดีกว่าที่จะแจ้งและแนะนำผู้ใช้:
System.out.println("Please enter your name");
String name=scan.next();
System.out.println("Your Name:"+name);
ในบรรทัดแรก เราถามผู้ใช้ว่าเราต้องการอะไรจากเขา จริงๆ แล้วสิ่งนี้ไม่เกี่ยวข้องกับสแกนเนอร์ แต่เป็นการดีเสมอที่จะให้คำแนะนำแก่ผู้ใช้ของคุณ ในบรรทัดที่สอง เราจะกำหนดค่าที่ผู้ใช้ป้อนลงในข้อมูลและบันทึกไว้เพื่อให้เราสามารถใช้ได้ในภายหลัง ในบรรทัดสุดท้ายเราจะเห็นว่าเราสามารถใช้ค่าที่ได้รับจากผู้ใช้ตามดุลยพินิจของเรา มาเพิ่มรายละเอียดเพิ่มเติมเล็กน้อยในโค้ดของเรา:
System.out.println("Please enter your last name");
String lastName=scan.next();
System.out.println("Your Name " + name + " " + "Your Last Name" + lastName);
โดยพื้นฐานแล้ว เราทำซ้ำสองบรรทัดก่อนหน้า ถามค่าจากผู้ใช้และบันทึกไว้ ในบรรทัดสุดท้ายเราใช้สองค่าที่เรานำมาจากผู้ใช้และตอนนี้ใช้ร่วมกัน
GO TO FULL VERSION