MỤC LỤC LỜI MỞ ĐẦU 2 PHẦN A: ĐA LUỒNG TRONG JAVA 2 I. Luồng trong Java là gì ? 2 II. Cách tạo và quản lý luồng trong Java 2 1. Tạo luồng bằng cách kế thừa từ lớp Thread 2 2. Tạo luồng bằng cách thực hiện từ Interface Runnable 2 III. Một số thông tin liên quan đến luồng 2 1. ThreadID 2 2. ThreadName 2 3. Độ ưu tiên của luồng (Priority) 2 4. Độ lớn ngăn xếp của luồng (StackSize) 2 IV. Các trạng thái luồng 2 V. Các trạng thái luồng do java định nghĩa 2 VI. Một số phương thức thông dụng 2 VII. Nhóm luồng 2 VIII. Đồng bộ hóa 2 PHẦN B: DEMO 2 I. Mô tả chương trình 2 II. Cấu trúc chương trình chương trình 2 KẾT LUẬN 2 TÀI LIỆU THAM KHẢO 2 LỜI MỞ ĐẦU Ngày nay, dưới sự phát triển nhanh chóng của khoa học kỹ thuật, một kỷ nguyên mới được mở ra, kỷ nguyên của công nghệ thông tin. Nhu cầu của loài người ngày càng lớn, đặc biệt là các ngành khoa học kỹ thuật khác đều cần tới sự hỗ trợ của công nghệ thông tin, mặc dù công nghệ phần cứng phát triển rất nhanh, CPU với tốc độ xử lý ngày càng được nâng cao, nhưng lại nảy sinh nhiều bài toán trong thực tế đòi hỏi thời gian thực hiện phải nhanh hơn nữa. Vấn đề xử lý song song đang ngày càng được nghiên cứu nhiều để giải quyết một số bài toán mà thực tế đang đặt ra, những vấn đề cần phải có kết quả trong một khoảng thời gian nhất định. Vì vậy, việc nghiên cứu các giải thuật cho xử lý song song đang là một yêu cầu và thách thức đối với các nhà lập trình phần mềm. Cùng với nhu cầu thiết yếu như vậy, vào năm 1991 Sun Microsystems đã cho ra đời ngôn ngữ lập trình Java. Ngôn ngữ lập trình Java hỗ trợ cho việc xử lý song song với cơ chế đa luồng. Thông qua bài tập lớn môn “Nguyên lý Hệ điều hành” nhóm chúng em xin trình bày một cách khái quát và cơ bản nhất về vấn đề “Phân luồng (Thread) trong Java”. PHẦN A: ĐA LUỒNG TRONG JAVA I. Luồng trong Java là gì? Luồng là đơn vị nhỏ nhất trong java có thể thực hiện được 1 công việc riêng biệt. Các luồng được quản lý bởi máy ảo java. Một ứng dụng java ngoài luồng chính có thể có các luồng khác thực thi đồng thời. Đa luồng giúp cho các tác vụ được xử lý độc lập giúp công việc được hoàn thành nhanh chóng. Trình duyệt web hay các chương trình chơi nhạc là 1 ví dụ điển hình về đa luồng. Khi duyệt 1 trang web, có rất nhiều hình ảnh, CSS, javascript... được tải đồng thời bởi các luồng khác nhau. Khi play nhạc, chúng ta vẫn có thể tương tác được với nút điều khiển như: Play, Pause, Next, Back ... vì luồng phát nhạc là luồng riêng biệt với luồng tiếp nhận tương tác của người dùng. Ưu điểm của đa luồng: Multithreading có chi phí thấp hơn Multiprocessing (về không gian, thời gian). Trong multiprocessing các tiến trình chạy trên các địa chỉ riêng biệt. Các luồng trong multithreading có thể chia sẻ cùng không gian bộ nhớ. Các tiến trình trong multiprocessing gọi nhau phải chịu chi phí lớn hơn các luồng trong multithreading. Multithreading cho phép chúng ta thiết kế chương trình hiệu quả hơn mà sử dụng ít tài nguyên CPU. Multithreading còn cho phép chúng ta điều khiển cho các luồng sleep một thời gian trong khi các luồng khác vẫn hoạt động mà không làm cho hệ thống bị pause. II. Cách tạo và quản lý luồng trong Java Trong java ta có thể tạo ra 1 luồng dễ dàng bằng cách tạo 1 đối tượng của lớp được thừa kế từ lớp Thread (java.lang.Thread) hoặc implements từ giao diện Runnable. Khi nào implements từ interface Runnable? Khi bạn muốn kế thừa từ 1 lớp khác ngoài lớp Thread, nếu bạn kế thừa nữa từ lớp Thread thì sẽ không được vì java không hỗ trợ đa thừa kế do đó ta phải implements từ interface Runnable. Trong trường hợp còn lại ta có thể kế thừa từ lớp Thread. 1. Tạo luồng bằng cách kế thừa từ lớp Thread Để tạo luồng bằng cách tạo lớp kế thừa từ lớp Thread, ta phải làm các công việc sau: Khai báo 1 lớp mới kế thừa từ lớp Thread. Override lại phương thức run ở lớp này, những gì trong phương thức run sẽ được thực thi khi luồng bắt đầu chạy. Sau khi luồng chạy xong tất cả các câu lệnh trong phương thức run thì luồng cũng tự hủy. Tạo 1 thể hiện (hay 1 đối tượng) của lớp ta vừa khai báo. Sau đó gọi phương thức start() của đối tượng này để bắt đầu thực thi luồng. Tuy ta khai báo những công việc cần làm của luồng trong phương thức run() nhưng khi thực thi luồng ta phải gọi phương thức start(). Vì đây là phương thức đặc biệt mà java xây dựng sẵn trong lớp Thread, phương thức này sẽ cấp phát tài nguyên cho luồng mới rồi chạy phương thức run() ở luồng này. Vì vậy, nếu ta gọi phương thức run() mà không gọi start() thì cũng như ta gọi 1 phương thức của 1 đối tượng bình thường và phương thức vẫn chạy trên luồng mà gọi phương thức chứ không chạy ở luồng mới tạo ra nên vẫn chỉ có 1 luồng chính làm việc chứ ứng dụng vẫn không phải là đa luồng. Ví dụ: Khai báo lớp mới ThreadX kế thừa từ lớp Thread và override phương thức run() : public class ThreadX extends Thread{ private String prefix=; public ThreadX(String p) { prefix=p;
Trang 1Khoa Công Nghệ Thông Tin
- -BÁO CÁO BÀI TẬP LỚN
ĐỀ TÀI: TÌM HIỂU CƠ CHẾ PHÂN LUỒNG TRONG JAVA VÀ DEMO MINH HỌA
Giáo viên hướng dẫn : Lê Đức Thuận Sinh viên thực hiện :
Hà Nội, 09/2014
Hà Nội, 09/2014
Trang 2LỜI MỞ ĐẦU 2
PHẦN A: ĐA LUỒNG TRONG JAVA 2
I Luồng trong Java là gì ? 2
II Cách tạo và quản lý luồng trong Java 2
1 Tạo luồng bằng cách kế thừa từ lớp Thread 2
2 Tạo luồng bằng cách thực hiện từ Interface Runnable 2
III Một số thông tin liên quan đến luồng 2
1 ThreadID 2
2 ThreadName 2
3 Độ ưu tiên của luồng (Priority) 2
4 Độ lớn ngăn xếp của luồng (StackSize) 2
IV Các trạng thái luồng 2
V Các trạng thái luồng do java định nghĩa 2
VI Một số phương thức thông dụng 2
VII Nhóm luồng 2
VIII Đồng bộ hóa 2
PHẦN B: DEMO 2
I Mô tả chương trình 2
II Cấu trúc chương trình chương trình 2
KẾT LUẬN 2
TÀI LIỆU THAM KHẢO 2
Trang 3LỜI MỞ ĐẦU
Ngày nay, dưới sự phát triển nhanh chóng của khoa học kỹ thuật, một kỷnguyên mới được mở ra, kỷ nguyên của công nghệ thông tin Nhu cầu của loàingười ngày càng lớn, đặc biệt là các ngành khoa học kỹ thuật khác đều cần tới
sự hỗ trợ của công nghệ thông tin, mặc dù công nghệ phần cứng phát triển rấtnhanh, CPU với tốc độ xử lý ngày càng được nâng cao, nhưng lại nảy sinh nhiềubài toán trong thực tế đòi hỏi thời gian thực hiện phải nhanh hơn nữa
Vấn đề xử lý song song đang ngày càng được nghiên cứu nhiều để giảiquyết một số bài toán mà thực tế đang đặt ra, những vấn đề cần phải có kết quảtrong một khoảng thời gian nhất định Vì vậy, việc nghiên cứu các giải thuật cho
xử lý song song đang là một yêu cầu và thách thức đối với các nhà lập trìnhphần mềm
Cùng với nhu cầu thiết yếu như vậy, vào năm 1991 Sun Microsystems đãcho ra đời ngôn ngữ lập trình Java Ngôn ngữ lập trình Java hỗ trợ cho việc xử
lý song song với cơ chế đa luồng
Thông qua bài tập lớn môn “Nguyên lý Hệ điều hành” nhóm chúng em xintrình bày một cách khái quát và cơ bản nhất về vấn đề “Phân luồng (Thread)trong Java”
Trang 4PHẦN A: ĐA LUỒNG TRONG JAVA
I Luồng trong Java là gì?
Luồng là đơn vị nhỏ nhất trong java có thể thực hiện được 1 công việc riêngbiệt Các luồng được quản lý bởi máy ảo java Một ứng dụng java ngoài luồngchính có thể có các luồng khác thực thi đồng thời Đa luồng giúp cho các tác vụđược xử lý độc lập giúp công việc được hoàn thành nhanh chóng Trình duyệtweb hay các chương trình chơi nhạc là 1 ví dụ điển hình về đa luồng
- Khi duyệt 1 trang web, có rất nhiều hình ảnh, CSS, javascript được tảiđồng thời bởi các luồng khác nhau
- Khi play nhạc, chúng ta vẫn có thể tương tác được với nút điều khiểnnhư: Play, Pause, Next, Back vì luồng phát nhạc là luồng riêng biệt vớiluồng tiếp nhận tương tác của người dùng
Ưu điểm của đa luồng:
- Multithreading có chi phí thấp hơn Multiprocessing (về không gian, thờigian) Trong multiprocessing các tiến trình chạy trên các địa chỉ riêngbiệt Các luồng trong multithreading có thể chia sẻ cùng không gian bộnhớ
- Các tiến trình trong multiprocessing gọi nhau phải chịu chi phí lớn hơncác luồng trong multithreading
- Multithreading cho phép chúng ta thiết kế chương trình hiệu quả hơn mà
sử dụng ít tài nguyên CPU
- Multithreading còn cho phép chúng ta điều khiển cho các luồng sleepmột thời gian trong khi các luồng khác vẫn hoạt động mà không làm cho
hệ thống bị pause
Trang 5II Cách tạo và quản lý luồng trong Java
Trong java ta có thể tạo ra 1 luồng dễ dàng bằng cách tạo 1 đối tượng củalớp được thừa kế từ lớp Thread (java.lang.Thread) hoặc implements từ giao diệnRunnable
Khi nào implements từ interface Runnable?
- Khi bạn muốn kế thừa từ 1 lớp khác ngoài lớp Thread, nếu bạn kế thừanữa từ lớp Thread thì sẽ không được vì java không hỗ trợ đa thừa kế do
đó ta phải implements từ interface Runnable
- Trong trường hợp còn lại ta có thể kế thừa từ lớp Thread
1 Tạo luồng bằng cách kế thừa từ lớp Thread
Để tạo luồng bằng cách tạo lớp kế thừa từ lớp Thread, ta phải làm các côngviệc sau:
- Khai báo 1 lớp mới kế thừa từ lớp Thread
- Override lại phương thức run ở lớp này, những gì trong phương thức run
sẽ được thực thi khi luồng bắt đầu chạy Sau khi luồng chạy xong tất cả cáccâu lệnh trong phương thức run thì luồng cũng tự hủy
- Tạo 1 thể hiện (hay 1 đối tượng) của lớp ta vừa khai báo
- Sau đó gọi phương thức start() của đối tượng này để bắt đầu thực thiluồng
Tuy ta khai báo những công việc cần làm của luồng trong phương thức run()nhưng khi thực thi luồng ta phải gọi phương thức start() Vì đây là phương thứcđặc biệt mà java xây dựng sẵn trong lớp Thread, phương thức này sẽ cấp phát tàinguyên cho luồng mới rồi chạy phương thức run() ở luồng này Vì vậy, nếu tagọi phương thức run() mà không gọi start() thì cũng như ta gọi 1 phương thứccủa 1 đối tượng bình thường và phương thức vẫn chạy trên luồng mà gọiphương thức chứ không chạy ở luồng mới tạo ra nên vẫn chỉ có 1 luồng chínhlàm việc chứ ứng dụng vẫn không phải là đa luồng
Trang 6Ví dụ:
- Khai báo lớp mới ThreadX kế thừa từ lớp Thread và override phươngthức run() :
public class ThreadX extends Thread{
private String prefix="";
public ThreadX(String p) {
prefix=p;
} public void run() {
for(int i=0;i<100;i++) System.out.println(prefix+i);
} }
- Tạo các đối tượng thuộc lớp ThreadX và start() chúng :
public class Main { public static void main(String[] args) { ThreadX t1=new ThreadX("Luồng thứ 1:");
ThreadX t2=new ThreadX("Luồng thứ 2:");
ThreadX t3=new ThreadX("Luồng thứ 3:");
Trang 7Hình 1 Tạo luồng bằng cách kế thừa từ lớp Thread.
Trang 82 Tạo luồng bằng cách thực hiện từ Interface Runnable
Để tạo luồng bằng cách hiện thực từ Interface Runnable, ta phải làm cáccông việc sau:
- Khai báo 1 lớp mới implements từ Interface Runnable
- Hiện thực phương thức run() ở lớp này, những gì trong phương thức run()
sẽ được thực thi khi luồng bắt đầu chạy Sau khi luồng chạy xong tất cả cáccâu lệnh trong phương thức run thì luồng cũng tự hủy
- Tạo 1 thể hiện (hay 1 đối tượng) của lớp ta vừa khai báo
(VD: Tên đối tượng là r1)
- Tạo 1 thể hiện của lớp Thread bằng phương thức khởi tạo:
public class RunX implements Runnable{
private String prefix="";
public RunX(String p) {
prefix=p;
} public void run() {
for(int i=0;i<100;i++) System.out.println(prefix+i);
}}
- Tạo các thể hiện của lớp RunX, Thread và start() chúng:
public class Main { public static void main(String[] args) { RunX r1=new RunX("Luồng thứ 1:");
RunX r2=new RunX("Luồng thứ 2:");
Trang 9RunX r3=new RunX("Luồng thứ 3:");
Thread t1=new Thread(r1);
Thread t2=new Thread(r2);
Thread t3=new Thread(r3);
t1.start();
t2.start();
t3.start();
}}
III Một số thông tin liên quan đến luồng
Luồng được thành lập bởi 1 định danh (ThreadID), bộ đếm chương trình(Counter), tập thanh ghi (Register) và ngăn xếp (Stack) Các luồng sẽ có 1 độ ưutiên (Priority) nhất định
1 ThreadID
ThreadID là định danh của luồng, nó dùng để phân biệt với các luồng kháccùng tiến trình hoặc cùng tập luồng Đây là thông số mà máy ảo java tự tạo rakhi ta tạo luồng nên ta không thể sửa đổi cũng như áp đặt thông số này khi tạoluồng Nhưng ta có thể lấy được nó thông qua phương thức getId() của lớpThread
Ví dụ:
public class Main { public static void main(String[] args) { ThreadX t1=new ThreadX("Luồng thứ 1:");
ThreadX t2=new ThreadX("Luồng thứ 2:");
ThreadX t3=new ThreadX("Luồng thứ 3:");
System.out.println("Tên luồng 1:"+t1.getName());
System.out.println("Tên luồng 2:"+t2.getName());
System.out.println("Tên luồng 3:"+t3.getName());
} }
Trang 11Ví dụ:
public class Main { public static void main(String[] args) { ThreadX t1=new ThreadX("Luồng thứ 1:");
ThreadX t2=new ThreadX("Luồng thứ 2:");
ThreadX t3=new ThreadX("Luồng thứ 3:");
System.out.println("Tên luồng 1:"+t1.getName());
System.out.println("Tên luồng 2:"+t2.getName());
System.out.println("Tên luồng 3:"+t3.getName());
} }
Kết quả:
Hình 3 Ví dụ về ThreadName
Trang 12Nếu muốn đặt tên cho luồng, ta có thể đặt tên thông qua phương thức khởi
tạo Thread(String name) hoặc phương thức void setName(String name).
Và ta có thể lấy tên luồng thông qua phương thức: Public String getName()
3 Độ ưu tiên của luồng (Priority)
Mỗi luồng có 1 độ ưu tiên nhất định Đây sẽ là thông số quyết định mức ưutiên khi cấp phát CPU cho các luồng Trong java, đế đặt độ ưu tiên cho 1 luồng
ta dùng phương thức void setPriority(int newPriority) với newPriority là giá
public class ThreadX extends Thread{
public ThreadX(String name)
public static void main(String[] args) {
ThreadX t1=new ThreadX("Luồng thứ 1");
ThreadX t2=new ThreadX("Luồng thứ 2");
ThreadX t3=new ThreadX("Luồng thứ 3");
Trang 13Hình 4 Ví dụ về Priority Luồng 3 có độ ưu tiên lớn nên được cấp CPU cao.
4 Độ lớn ngăn xếp của luồng (StackSize)
StackSize là độ lớn của ngăn xếp (tính bằng byte) mà luồng có thể dùngtrong quá trình thực thi Nếu ta không quy định giá trị này hoặc đặt giá trị nàybằng 0 thì nó sẽ phụ thuộc vào giá trị mặc định mà JMV quy định và JMV sẽ tựđiều chỉnh cho hợp lý Còn nếu ta có quy định, thread sẽ chỉ cho phép dùngStack tới mức tối đa mà giá trị này quy định
IV Các trạng thái luồng
Sơ đồ dưới đây mô tả tổng quan về các trạng thái mà luồng có thề có trong
Trang 14Hình 5 Các trạng thái luồng
New Thread: Đây là trạng thái khi luồng vừa được khởi tạo bằng phương
thức khởi tạo của lớp Thread nhưng chưa được start() Ở trạng thái này, luồngđược tạo ra nhưng chưa được cấp phát tài nguyên và cũng chưa chạy Nếu luồngđang ở trạng thái này mà ta gọi các phương thức ép buộc stop, resume, suspend
… sẽ là nguyên nhân sảy ra ngoại lệ IllegalThreadStateException
VD: Thread test=new Thread();
Runnable: Xét code sau:
Thread test=new Thread();
test.start()
Sau khi gọi phương thức start() thì luồng test đã được cấp phát tài nguyên vàcác lịch điều phối CPU cho luồng test cũng bắt đầu có hiệu lực Ở đây, chúng tadùng trạng thái là Runnable chứ không phải Running, vì như đã nói ở phần đầu(Các mô hình đa luồng) thì luồng không thực sự luôn chạy mà tùy vào hệ thống
mà có sự điều phối CPU khác nhau
Luồng sẽ ở trạng thái Runnable này từ khi luồng được gọi phương thứcstart() và trước khi luồng kết thúc các công việc trong phương thức run() hoặctrước khi sảy ra 1 ngoại lệ nào đó trong run() khiến run() bị kết thúc Một dốtrường hợp nếu ta tự ý stop() hoặc destroy() luồng thì cũng khiến luồng rời khỏitrạng thái runnable
Trang 15Not Runnable: Một luồng bị rơi vào trạng thái “Not Runable” thì do 1
trong bốn nguyên nhân sau:
- Luồng bị tạm ngưng 1 khoảng nhất định do bị gọi phương thức sleep(long milisecond)
- Luồng bị tạm ngưng cấp CPU do bị gọi phương thức suspend()
- Luồng bị gọi phương thức wait() để tạm ngưng để chờ 1 điều kiện nào đóthay đổi khác với hiện tại
- Luồng đang bị Block vì phải chờ I/O Ví dụ: trong lúc chờ người dùngnhập dữ liệu vào bàn phím, luồng bị Block
Ví dụ:
try { Thread.sleep(10000);
} catch (InterruptedException e){}
Trong ví dụ trên, luồng sẽ tạm ngưng làm việc trong suốt 10000 mili giây(10 giây) Tuy nhiên, cần lưu ý 1 điều là: khác với suspend(), khi sleep() luồngvẫn được cấp CPU, nhưng luồng không làm gì cả, còn suspend() luồng sẽ bịngưng cấp CPU
Ngoài ra, cũng có 1 điều lưu ý khác : aLuồng bị “Not Runnable” bởi nguyênnhân nào thì phải cho luồng chạy lại bởi 1 tác động thích hợp với đúng nguyênnhân đó Cụ thể như sau:
- Nếu luồng bị Sleep, phải đợi cho đến khi hết thời gian chỉ định sleep thìluồng sẽ tự chạy lại
- Nếu luồng bị suspend() ta phải gọi phương thức resume() để tiếp tục lại
- Nếu luồng đang wait() , tức là chờ đợi 1 điều kiện nào đó thì luồng sở hữuđiều kiện đó phải gọi phương thức notify() hoặc notifyall() để thông báo choluồng chạy lại
- Nếu luồng đang bị Block vì I/O thì quá trình I/O phải được hoàn tất
Trang 16Như vậy, nếu luồng bị sleep 10 giây, mà nếu mới trải qua 5 giây, dù ta có gọi phương thức resume() thì luồng vẫn không thể chạy lại mà sẽ xảy ra ngoại lệ(Sẽ đề cập các ngoại lệ sâu hơn ở phần sau)
Dead: Một thread bị rơi vào trạng thái Dead do 1 trong 2 cách: Chết tự
nhiên hoặc bị ép dừng lại Một thread sẽ chết 1 cách tự nhiên khi nó hoàn thànhcác lệnh trong phương thức run() Bạn cũng có thể kết thúc 1 luồng bất kỳ lúcnào bằng cách gọi phương thức stop()
V Các trạng thái luồng do java định nghĩa
Ở phần trên, chúng ta đã đề cập chi tiết đến các trạng thái chung nhất củaluồng và các nguyên nhận đưa luồng vào trạng thái đó cũng như cách đưa luồngthoát khỏi trạng thái đó Ở phần này chúng ta sẽ đề cập đến cụ thể các trạng tháicủa luồng theo cách định nghĩa của java ở những trường hợp cụ thể bởi cácnguyên nhận cụ thế
Java định nghĩa các trạng thái của luồng trong Thread.State:
Thread.State.WAITING
Đây là 1 dạng của trạng thái “Not Runnable” Thread đang chờ 1 notify() từ
1 thread khác Thread rơi vào trạng thái này do phương thức wait() hoặc join()
Trang 17Đây là 1 dạng của trạng thái “Not Runnable” Thread đang chờ 1 notify() từ
1 thread khác trong 1 thời gian nhất định, Thread rơi vào trạng thái này dophương thức wait(long timeout) hoặc join(long timeout)
Thread.State.TERMINATED
Thread đã hoàn thành công việc trong run() hoặc bị stop()
VI Một số phương thức thông dụng
activeCount(): Trả về số thread hiện tại có trong ThreadGroup.
checkAccess(): Kiểm tra xem thread đang chạy có quyền thay đổi nhóm
thread này hay không
currentThread(): Đây là một phương thức tĩnh, có nghĩa là bạn có thể gọi
nó bất kỳ lúc nào ngay cả khi chưa khởi tạo luồng Phương thức này trả về mộtđối tượng của lớp Thread, đối tượng này chính là luồng đang được thực hiệntrong thời điểm hiện tại
destroy(): Dừng hẳn luồng.
getId(): Trả về số nguyên nào đó là định danh của luồng.
getName(): Trả về tên của luồng
getPriority(): lấy độ ưu tiên của một Thread
getState(): Trả về trạng thái của luồng với các giá trị sau.
getThreadGroup(): Trả về nhóm Thread mà thread này thuộc về.
isAlive(): Trả về true nếu luồng vẫn đang hoạt động (luồng còn sống) Trả
về false nếu luồng đã thực hiện xong và dừng lại
resume(): Tiếp tục chạy luồng.
setName(String name): Thay đổi tên của thread bằng tên name.
Trang 18sleep(long millis): Tạm dừng luồng trong một khoảng thời gian millis giây start(): Dùng để bắt đầu chạy một luồng, nếu không gọi phương thức này
thì do dù bạn đã tạo một thể hiện của luồng thì nó vẫn ko có ý nghĩa gì cả
stop(): Tạm dừng luồng lại không thực hiện nữa.
suspend(): Tạm dừng hoạt động của 1 luồng nào đó bằng các ngưng cung
cấp CPU cho luồng này
yield(): Tạm dừng luồng hiện tại để cho luồng khác hoạt động.
VII Nhóm luồng
Nhóm luồng là một tập hợp gồm nhiều luồng, khi ta tác động đến nhómluồng (chẳng hạn như đa tạm ngưng…) thì tất cả các luồng trong nhóm đều nhậnđược cùng tác động đó, điều này là tiện lợi khi ta muốn quản lý nhiều luồng thựchiện các tác vụ tương tự nhau
Để tạo một nhóm luồng ta cần:
- Tạo ra một nhóm luồng bằng cách sử dụng phương thức tạo dựng của lớpThreadGroup():
ThreadGroup g = new ThreadGroup(“ThreadGroupName”);
- Đưa các luồng vào nhóm luồng dùng phương thức tạo dựng của lớpThread():
Thread() = new Thread(g, new ThreadClass(),”ThisThread”);
VIII Đồng bộ hóa
Tất cả các luồng của một quá trình thì được thực thi song song và độc lậpnhau nhưng lại cùng chia sẻ nhau một không gian địa chỉ của quá trình Chính vìvậy có thể dẫn đến khả năng đụng độ trong việc cập nhật dữ liệu dùng chungcủa chương trình (biến, các tập tin)
VD: Một luồng có thể cố gắng đọc dữ liệu, trong khi luồng khác cố gắngthay đổi dữ liệu ấy -> dữ liệu có thể sai