Thảo luận Bài 5
+72
LeThanhQuang (I22B)
NguyenTrongTinh(I22A)
MaiNguyenThanhLong(I22A)
QuangMinhTuan(I22B)
NguyenThiMai(I22A)
NguyenThiNgocPhuoc(122A)
LeNgocTung (I22A)
LETHIANHDAO48(I22B)
lekhanhhoa(I22B)
NguyenVanQuoc (I22B)
HaTrungMinhPhuc(I22B)
NguyenBaoLoc70(I22A)
PhamThiThao (I22B)
DuongKhanhThanh(I22B)
nguyenhoanglam_I22B
phungvanduong24(I12A)
tranngochuy(I22B)
NguyenCaoDuong(I22B)
phanthanhcan(I22A)
DuongTrungQuan
tranvanminh82(I22A)
NguyenKhanhDuy18 (I22B)
TranQuangTien(I22A)
NguyenNgocDan(I22B)
TrỉnhToQuyen(I12A)
vivanbieu(I22B)
VanNhatDongGiang(I22A)
NguyenVanSang(I22A)
TranThienTam (I22A)
NguyenPhuongNhu(I22B)
HuynhHuuTai(I22A)
Dao Duy Thanh(I22B)
NguyenVanTu(I22A)
dangvannhan(I22A)
NguyenVanPhat(I22B)
TruongTranThanhTu(I22B)
VoMinhThang(I22B)
VoMinhDien(I22B)
MaiXuanSon (I22B)
NguyenHuuMinh80(I22B)
dangthihoangly(I12A)
NguyenTienDat (I22A)
truongtph.i11c
NguyenHoangThien(I22B)
TranDangKhoa(I22A)
LeThiKimNgan67(I11C)
TranVuSang (I22B)
HongGiaPhu (I22A)
BuiTrongHung41(I11C)
NgT.KimHuyen(I22A)
PhamXuanThieu (I22A)
LêAnhNgữ(I22A)
nguyenthithutrang (I11C)
PhamQuocCuong (I22A)
NguyenHuuThien159 (I22B)
BuiThucTuan(I22B)
cat
NguyenBacHoi(I22B)
NguyenNhatHuy64(I22B)
LeAnhToan48(I22B)
NguyenTanDat(I22B)
dangmonghai(I12A)
NguyenManhHuy(I22B)
NgoVanTuyen(I22B)
NguyenHoangKimVu (I11C)
ChauQuangCam (I22B)
NguyenQuocHuy (I22B)
NguyenQuangHuy(I22B)
NguyenThanhQuoc(I22A)
HuynhDucQuang(I22B)
HoangThanhThien(I22B)
Admin
76 posters
Trang 3 trong tổng số 8 trang
Trang 3 trong tổng số 8 trang • 1, 2, 3, 4, 5, 6, 7, 8
Tại sao đa luồng làm việc hiệu quả hơn so với đơn luồng??
Trước tiên, để giải quyết câu hỏi này, theo mình nên so sánh hai vấn đề cần đặt ra: đó là đa luồng với đơn luồng và luồng - tiến trình để nhận thấy đa luồng (Multi Thread) làm việc hiệu quả hơn so với đơn luồng (Single Thread) và tiến trình truyền thống (Heavy Weight Process)
1. So sánh Đa luồng và Đơn luồng: (để thấy được đa luồng tích cực hơn đơn luồng)
- Giải quyết được bài toán về thời gian.
- Giải quyết được độ trễ (delay) khi thực hiện công việc xử lý.
- Giải quyết được tình trạng tăng tốc và đồng bộ khi xử lý dữ liệu.
- Tài nguyên được trả về rỗng khi thực hiện xong công việc (đa luồng) so với từng đợt, từng đợt trả trả về (đơn luồng) -> Đỡ chiếm nguồn tài nguyên trong khoảng thời gian
2. So sánh luồng với tiến trình
- Khi hoạt động, luồng chiếm dụng tài nguyên (CPU) ít hơn so với tiến trình
- Vấn đề chia sẽ tài nguyên, thông tin giữa các luồng linh động hơn, truy xuất được nhanh hơn (do có nhiều luồng phụ hoạt động song song và đồng thời).
- Khi tiến trình bị ngắt trong quá trình vận hành, do lỗi của hệ thống, tiến trình có thể bị gián đoạn. Trong khi đó, nếu luồng trong trạng thái bận, chưa kịp phản hồi thì những luồng phụ được hoạt động -> đảm bảo hoàn thành công việc.
Từ hai kết quả so sánh trên theo ý của mình, để nhận thấy luồng (thread) hoạt động tích cực, hiệu quả hơn so với tiến trình truyền thống (Process), mong nhận được sự góp ý thêm từ phía Thầy và các bạn!
1. So sánh Đa luồng và Đơn luồng: (để thấy được đa luồng tích cực hơn đơn luồng)
- Giải quyết được bài toán về thời gian.
- Giải quyết được độ trễ (delay) khi thực hiện công việc xử lý.
- Giải quyết được tình trạng tăng tốc và đồng bộ khi xử lý dữ liệu.
- Tài nguyên được trả về rỗng khi thực hiện xong công việc (đa luồng) so với từng đợt, từng đợt trả trả về (đơn luồng) -> Đỡ chiếm nguồn tài nguyên trong khoảng thời gian
2. So sánh luồng với tiến trình
- Khi hoạt động, luồng chiếm dụng tài nguyên (CPU) ít hơn so với tiến trình
- Vấn đề chia sẽ tài nguyên, thông tin giữa các luồng linh động hơn, truy xuất được nhanh hơn (do có nhiều luồng phụ hoạt động song song và đồng thời).
- Khi tiến trình bị ngắt trong quá trình vận hành, do lỗi của hệ thống, tiến trình có thể bị gián đoạn. Trong khi đó, nếu luồng trong trạng thái bận, chưa kịp phản hồi thì những luồng phụ được hoạt động -> đảm bảo hoàn thành công việc.
Từ hai kết quả so sánh trên theo ý của mình, để nhận thấy luồng (thread) hoạt động tích cực, hiệu quả hơn so với tiến trình truyền thống (Process), mong nhận được sự góp ý thêm từ phía Thầy và các bạn!
TranDangKhoa(I22A)- Tổng số bài gửi : 32
Join date : 10/03/2013
Age : 33
Đến từ : Lớp I22A
Câu 1: Phân biệt khái niện luồng với tiến trình. Và trình bày những lợi ích của công nghệ đa luồng
Phân biệt khái niệm luồng với tiến trình
• Luồng: là tiến trình nhẹ (LWP - Light Weight Process), một đơn vị cơ bản sử dụng CPU. Luồng cũng có thông tin trạng thái như của tiến trình hệ thống (HWP - Heavy Weight Process)
Ví dụ: Lớp học là một tiến trình. Trong lớp sẽ có một giáo viên(đơn luồng) và các học viên (đa luồng)
• Tiến trình: là chương trình trong thời gian thực hiện (đặt dưới sự quản lý của hệ điều hành). Có sự phân biệt Tiến trình hệ thống (của Hệ điều hành) với Tiến trình người dùng.
Ví dụ: Lớp HCTH102C đang học là một tiến trình
Giống nhau: đều là tiến trình máy tính.
Khác nhau: luồng là tiến trình nhẹ được quản lý bởi 1 tiến trình chính, sử dụng ít CPU hơn, trong khi tiến trình nặng được quản lý bởi hệ điều hành, chiếm nhiều CPU hơn
Những ích lợi của công nghệ đa luồng
• Khả năng đáp ứng (Responsiveness) tốt hơn: Trong khi một luồng bị ách hoặc quá bận, luồng khác vẫn vận hành bình thường (Luồng chính của trình duyệt vẫn tương tác với người dùng trong khi dữ liệu được lấy về).
Ví dụ: Các cô ở tổng đài 108 là các luồng. Khi khách hàng điện thoại hỏi 108, thì một trong các cô (cô thứ 1) sẽ trả lời. Nếu trong thời điểm đó khách hàng thứ hai gọi 108, thì một trong các cô (cô thứ 2) còn lại sẽ trả lời cho khách hàng.
• Chia sẻ tài nguyên (Resource Sharing): Theo mặc định, các luồng có thể dùng chung bộ nhớ và tài nguyên của luồng cha. Vài luồng cùng vận hành trong 1 vùng địa chỉ, do đó dễ dùng chung tài nguyên hơn so với trường hợp đa tiến trình.
Ví dụ: Trong lớp học thầy (tiến trình chính) điều khiển hoạt động của học sinh (luồng). Cả lớp sử dụng chung bảng, máy chiếu, micro (tài nguyên chung)
• Tiết kiệm (Economy): Cấp phát bộ nhớ và tài nguyên cho tiến trình là công việc tốn kém. Do luồng chung tài nguyên với cha và các luồng khác, việc tạo lập và chuyển ngữ cảnh cũng nhanh hơn (Solaris 2: Tạo tiến trình chậm hơn 30 lần, Chuyển ngữ cảnh chậm hơn 5 lần).
Ví dụ: Trong nhà tiến trình) có anh/chị (luồng) lập gia đình. Bố mẹ ngăn phòng cho anh/chị ở riêng (chia sẻ tài nguyên) sẽ đỡ tốn kém hơn nhiều so với việc mua một căn nhà mới (cấp phát tài nguyên mới)
• Tận dụng được thế mạnh của kiến trúc đa xử lý: Đa luồng làm tăng tính song song trên hệ máy nhiều CPU. Mỗi luồng có thể chạy bởi CPU riêng.
Lập trình đa luồng dễ hơn lập trình đa tiến tình
• Luồng: là tiến trình nhẹ (LWP - Light Weight Process), một đơn vị cơ bản sử dụng CPU. Luồng cũng có thông tin trạng thái như của tiến trình hệ thống (HWP - Heavy Weight Process)
Ví dụ: Lớp học là một tiến trình. Trong lớp sẽ có một giáo viên(đơn luồng) và các học viên (đa luồng)
• Tiến trình: là chương trình trong thời gian thực hiện (đặt dưới sự quản lý của hệ điều hành). Có sự phân biệt Tiến trình hệ thống (của Hệ điều hành) với Tiến trình người dùng.
Ví dụ: Lớp HCTH102C đang học là một tiến trình
Giống nhau: đều là tiến trình máy tính.
Khác nhau: luồng là tiến trình nhẹ được quản lý bởi 1 tiến trình chính, sử dụng ít CPU hơn, trong khi tiến trình nặng được quản lý bởi hệ điều hành, chiếm nhiều CPU hơn
Những ích lợi của công nghệ đa luồng
• Khả năng đáp ứng (Responsiveness) tốt hơn: Trong khi một luồng bị ách hoặc quá bận, luồng khác vẫn vận hành bình thường (Luồng chính của trình duyệt vẫn tương tác với người dùng trong khi dữ liệu được lấy về).
Ví dụ: Các cô ở tổng đài 108 là các luồng. Khi khách hàng điện thoại hỏi 108, thì một trong các cô (cô thứ 1) sẽ trả lời. Nếu trong thời điểm đó khách hàng thứ hai gọi 108, thì một trong các cô (cô thứ 2) còn lại sẽ trả lời cho khách hàng.
• Chia sẻ tài nguyên (Resource Sharing): Theo mặc định, các luồng có thể dùng chung bộ nhớ và tài nguyên của luồng cha. Vài luồng cùng vận hành trong 1 vùng địa chỉ, do đó dễ dùng chung tài nguyên hơn so với trường hợp đa tiến trình.
Ví dụ: Trong lớp học thầy (tiến trình chính) điều khiển hoạt động của học sinh (luồng). Cả lớp sử dụng chung bảng, máy chiếu, micro (tài nguyên chung)
• Tiết kiệm (Economy): Cấp phát bộ nhớ và tài nguyên cho tiến trình là công việc tốn kém. Do luồng chung tài nguyên với cha và các luồng khác, việc tạo lập và chuyển ngữ cảnh cũng nhanh hơn (Solaris 2: Tạo tiến trình chậm hơn 30 lần, Chuyển ngữ cảnh chậm hơn 5 lần).
Ví dụ: Trong nhà tiến trình) có anh/chị (luồng) lập gia đình. Bố mẹ ngăn phòng cho anh/chị ở riêng (chia sẻ tài nguyên) sẽ đỡ tốn kém hơn nhiều so với việc mua một căn nhà mới (cấp phát tài nguyên mới)
• Tận dụng được thế mạnh của kiến trúc đa xử lý: Đa luồng làm tăng tính song song trên hệ máy nhiều CPU. Mỗi luồng có thể chạy bởi CPU riêng.
Lập trình đa luồng dễ hơn lập trình đa tiến tình
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Ví dụ về "Tập luồng" (Thread Pools)
Trong thực tiễn, có nhiều ví dụ về "Tập luồng" (Thread Pools), ví dụ của mình như sau:
Bạn A đi làm tại ngân hàng Đông Á, bạn A được ban Quản lý phát cho mình 3 bộ đồng phục (được thay phiên nhau trong 6 ngày làm việc tại Ngân hàng). Cứ hai ngày lại được thay một bộ đồng phục, tương ứng 3*2=6. Sau hai ngày làm việc, A lại giặt đồng phục của mình sạch sẽ và phơi lên, để chuẩn bị cho những ngày làm việc kế tiếp.
Như vậy, từ ví dụ về đồng phục của bạn A, ta cũng có thể liên tưởng:
- Việc "giặt đồ" đóng vai trò như là một tiến trình cha (luồng cha)
- "Đồng phục mới (được giặt giũ sạch sẽ)" cũng giống như các luồng đang trực tiếp sẵn sàng chờ công việc.
- "Khi A có công việc gấp" (phải đi công tác đột ngột) cũng giống như luồng đã bắt đầu thực thi công việc.
-"Sau khi đồng phục bẩn", A tranh thủ giặt giũ đồng phục và phơi lên khi có công việc cần (chờ luồng cha gọi).
TranDangKhoa(I22A)- Tổng số bài gửi : 32
Join date : 10/03/2013
Age : 33
Đến từ : Lớp I22A
Câu 2: Trình bày nguyên lý tập nguồn và cho ví dụ minh họa
Tập luồng (Thread Pools):
• Tiến trình cha tạo lập sẵn một tập luồng khi khởi động.
• Các luồng trong tập luồng luôn sẵn sàng chờ công việc.
• Khi tiến trình cha (ví dụ Web Server) nhận thêm một yêu cầu, một luồng được đánh thức và đưa vào vận hành.
• Phục vụ xong, luồng được đưa trả về tập luồng.
• Nếu số yêu cầu lớn hơn số luồng trong tập, tiến trình cha chờ đến khi có luồng được giải phóng.
Ví dụ:
Trong một doanh trai quân đội sẽ có một tướng lĩnh (tiến trình cha) và sẽ có một đội binh (tập luồng).
Đội binh này sẽ sẳn sàng chiến đầu khi có mệnh lệnh (sẵn sàng chờ công việc).
Khi có một tên địch đột nhập, Tướng lĩnh sẽ điều binh sĩ 1 (một luồng) đi bắt tên địch (một luồng được đánh thức và đưa vào vận hành).
Trong khi đó, lại có thêm một tên địch khác đột nhập (nhận thêm một yêu cầu), Tướng lĩnh sẽ điều binh sĩ 2 (một luồng) đi bắt địch (một luồng khác được đánh thức và đưa vào vận hành).
Sau khi bắt địch xong, binh sĩ sẽ trở về doanh trại (luồng được trả về tập luồng)
Ví dụ trong máy tính: Web server ban đầu phát sinh 100 luồng ở trạng thái ready. Khi trình duyệt gửi yêu cầu truy cập 1 trang web đến, Web server sẽ đánh thức 1 luồng để phục vụ cho trình duyệt. Khi có 1 trình duyệt khác yêu cầu, thì web server tiếp tục đánh thức 1 luồng khác. Khi 1 luồng thực hiện xong nhiệm vụ sẽ quay lại web server và chờ ở trạng thái ready. Giả sử có nhiều hơn 100 trình duyệt gửi yêu cầu, thì một số trình duyệt sẽ phải chờ 1 luồng xong nhiệm vụ mới phục vụ tiếp
• Tiến trình cha tạo lập sẵn một tập luồng khi khởi động.
• Các luồng trong tập luồng luôn sẵn sàng chờ công việc.
• Khi tiến trình cha (ví dụ Web Server) nhận thêm một yêu cầu, một luồng được đánh thức và đưa vào vận hành.
• Phục vụ xong, luồng được đưa trả về tập luồng.
• Nếu số yêu cầu lớn hơn số luồng trong tập, tiến trình cha chờ đến khi có luồng được giải phóng.
Ví dụ:
Trong một doanh trai quân đội sẽ có một tướng lĩnh (tiến trình cha) và sẽ có một đội binh (tập luồng).
Đội binh này sẽ sẳn sàng chiến đầu khi có mệnh lệnh (sẵn sàng chờ công việc).
Khi có một tên địch đột nhập, Tướng lĩnh sẽ điều binh sĩ 1 (một luồng) đi bắt tên địch (một luồng được đánh thức và đưa vào vận hành).
Trong khi đó, lại có thêm một tên địch khác đột nhập (nhận thêm một yêu cầu), Tướng lĩnh sẽ điều binh sĩ 2 (một luồng) đi bắt địch (một luồng khác được đánh thức và đưa vào vận hành).
Sau khi bắt địch xong, binh sĩ sẽ trở về doanh trại (luồng được trả về tập luồng)
Ví dụ trong máy tính: Web server ban đầu phát sinh 100 luồng ở trạng thái ready. Khi trình duyệt gửi yêu cầu truy cập 1 trang web đến, Web server sẽ đánh thức 1 luồng để phục vụ cho trình duyệt. Khi có 1 trình duyệt khác yêu cầu, thì web server tiếp tục đánh thức 1 luồng khác. Khi 1 luồng thực hiện xong nhiệm vụ sẽ quay lại web server và chờ ở trạng thái ready. Giả sử có nhiều hơn 100 trình duyệt gửi yêu cầu, thì một số trình duyệt sẽ phải chờ 1 luồng xong nhiệm vụ mới phục vụ tiếp
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Ví dụ thực tế về tính hiệu quả của lập trình đa luồng
Năm 1999. internet ở Việt Nam chưa phổ biến, nhà nước và các công ty lớn sử dụng mạng vitranet của microsoft. Các client sẽ quay số đến server để truy xuất 1 trang web. Database = SQL server, hệ điều hành: NT 4.0. Công ty mạng Phương Nam phát triển 1 trang web giới thiệu việc làm qua mạng. Client quay số đến và giới thiệu bản thân, mức lương yêu cầu để đăng lên web. Nhược điểm của ứng dụng này là: khi có 5 client cùng quay số đến địa chỉ giới thiệu việc làm thì server bị treo. Công ty mời thầy đến để kiểm tra và lãnh đạo công ty cho rằng bị hư phần cứng. Không cần kiểm tra phần cứng, thầy đã chỉ ra ngay vấn đề của ứng dụng là do công ty sử dụng công nghệ CGI (common gateway interface) là công nghệ lập trình đa tiến trình. Với công nghệ này, khi có 1 client quay số đến thì CGI sẽ phát sinh 1 tiến trình nặng để thực hiện. 5 tiến trình nặng chạy 1 lúc trên server sẽ làm server bị treo. Giải pháp: thầy viết lại ứng dụng bằng công nghệ ASP (active server pages) là công nghệ đa luồng. Khi sử dụng công nghệ này thì mỗi client khi quay số đến sẽ được phục vụ bằng 1 luồng (nhẹ hơn tiến trình) nên server sẽ không bị treo.
Admin
Không phải vậy !
Admin
Không phải vậy !
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
CPU của Intel sử dụng công nghệ đa luồng
1. Pentium D
Thế hệ đầu tiên và có thể nói là có nhiều nhược điểm nhất là Pentium D.
- Cache trên thực tế được áp dụng công nghệ Share Cache của hai nhân. Nhưng thực tế lớn nhất chỉ có 2.77 MB cho 4.0 MB lý thuyết
- Sức mạnh xử lý đa luồng được nhiều người mong đợi nhưng khá thất vọng.
- Sử dụng hai nhân có xung quá cao, sự điều phối xử lý chưa được thông minh cho lắm dẫn đến khi chạy tiêu thụ điện năng quá cao làm cho CPU rất nóng. Đây là nhược điểm nhiều người phàn nàn nhất.
- Chưa được áp dụng những công nghệ mới của kiến trúc Core.
Có thể nói Pentium D mới chỉ là thử nghiệm cho thế hệ đa nhân của Intel nên chưa thực sư đáp ứng mong đợi.
Những ưu điểm nổi trội của Pentium D:
- Sức mạnh sử lý đa luồng mạnh hơn Petium 4 rất nhiều .
- Bộ đệm được trang bị lên gấp đôi trên lý thuyết và 150% trên thực tế.
Pentium D phổ biến nhất ngày nay là
D925 - 3.0 GHz - 4.0 MB Cache L2 - Rated Bus 800 MHz - Speed Bus 233 MHz - Data Width 64 Bit . Lớn nhất có Pentium D 3.4 GHz - 4.0 MB Cache L2 - Rated Bus 800 MHz - Speed Bus 233 MHz - Data Width 64 Bit.
2.Pentium Dual Core
Đây là thế hệ đa nhân ngay sau Pentium D .
Ưu điểm : Hai nhân nên xử lý đa luồng rất mạnh .
- Điều phối xử lý thông mình hơn nên có thể hạ thấp được xung nhịp của Cores xuống còn 1.6 GHz (E2140), 1.8 GHz (E2160), 2.0 GHz (E2180). Do vậy tiết kiệm điện và tỏa ít nhiệt lượng hơn, khắc phục được nhược điểm lớn nhất của Pentium D.
- Thực tế nếu được hỗ trợ thêm GPU của VGA mạnh thì Pentium Dual Core chạy rất mạnh trong các tác vụ xử lý đồ họa cao cấp.
- Sử dụng kiến trúc Intel Core mới nhất của Intel (được áp dụng trong các CPU Core 2 thế hệ sau).
Nhược điểm:
- Share Cache trên nền Lõi cũ nên chỉ tăng được L2 Cache lên 1.0 MB.
3.Core 2 Duo, Core 2 Extreme và Core 2 Quad
Có đầy đủ các ưu điểm của Pentium E. Ngoài ra còn có các cải tiến sau.
- Khả năng điều phối sử lý thông minh hơn nhiều, điều này có hai tác dụng.
Thứ nhất là tăng khả năng xử lý trên lý thuyết lên đến 40%.
Sức mạnh xử lý đa luồng cũng mạnh lên rất nhiều
- Áp dụng công nghệ Share Cache tăng gấp đôi dung lượng bộ đệm trên lý thuyết và 165% trên thực tế.
- Tiết kiệm điện năng khoảng 40% có được nhờ công nghệ chia sẻ xử lý thông minh.
Thế hệ đầu tiên và có thể nói là có nhiều nhược điểm nhất là Pentium D.
- Cache trên thực tế được áp dụng công nghệ Share Cache của hai nhân. Nhưng thực tế lớn nhất chỉ có 2.77 MB cho 4.0 MB lý thuyết
- Sức mạnh xử lý đa luồng được nhiều người mong đợi nhưng khá thất vọng.
- Sử dụng hai nhân có xung quá cao, sự điều phối xử lý chưa được thông minh cho lắm dẫn đến khi chạy tiêu thụ điện năng quá cao làm cho CPU rất nóng. Đây là nhược điểm nhiều người phàn nàn nhất.
- Chưa được áp dụng những công nghệ mới của kiến trúc Core.
Có thể nói Pentium D mới chỉ là thử nghiệm cho thế hệ đa nhân của Intel nên chưa thực sư đáp ứng mong đợi.
Những ưu điểm nổi trội của Pentium D:
- Sức mạnh sử lý đa luồng mạnh hơn Petium 4 rất nhiều .
- Bộ đệm được trang bị lên gấp đôi trên lý thuyết và 150% trên thực tế.
Pentium D phổ biến nhất ngày nay là
D925 - 3.0 GHz - 4.0 MB Cache L2 - Rated Bus 800 MHz - Speed Bus 233 MHz - Data Width 64 Bit . Lớn nhất có Pentium D 3.4 GHz - 4.0 MB Cache L2 - Rated Bus 800 MHz - Speed Bus 233 MHz - Data Width 64 Bit.
2.Pentium Dual Core
Đây là thế hệ đa nhân ngay sau Pentium D .
Ưu điểm : Hai nhân nên xử lý đa luồng rất mạnh .
- Điều phối xử lý thông mình hơn nên có thể hạ thấp được xung nhịp của Cores xuống còn 1.6 GHz (E2140), 1.8 GHz (E2160), 2.0 GHz (E2180). Do vậy tiết kiệm điện và tỏa ít nhiệt lượng hơn, khắc phục được nhược điểm lớn nhất của Pentium D.
- Thực tế nếu được hỗ trợ thêm GPU của VGA mạnh thì Pentium Dual Core chạy rất mạnh trong các tác vụ xử lý đồ họa cao cấp.
- Sử dụng kiến trúc Intel Core mới nhất của Intel (được áp dụng trong các CPU Core 2 thế hệ sau).
Nhược điểm:
- Share Cache trên nền Lõi cũ nên chỉ tăng được L2 Cache lên 1.0 MB.
3.Core 2 Duo, Core 2 Extreme và Core 2 Quad
Có đầy đủ các ưu điểm của Pentium E. Ngoài ra còn có các cải tiến sau.
- Khả năng điều phối sử lý thông minh hơn nhiều, điều này có hai tác dụng.
Thứ nhất là tăng khả năng xử lý trên lý thuyết lên đến 40%.
Sức mạnh xử lý đa luồng cũng mạnh lên rất nhiều
- Áp dụng công nghệ Share Cache tăng gấp đôi dung lượng bộ đệm trên lý thuyết và 165% trên thực tế.
- Tiết kiệm điện năng khoảng 40% có được nhờ công nghệ chia sẻ xử lý thông minh.
truongtph.i11c- Tổng số bài gửi : 26
Join date : 26/08/2011
Re: Thảo luận Bài 5
Thêm một ví dụ:LeAnhToan48(I22B) đã viết:Vì tạo luồng dễ dàng, nhanh và ít tốn kém hơn là tạo hẳn một tiến trình. Tạo một tiến trình thì khó, chậm và tốn nhiều thời gian, chi phí.
Ví dụ: thêm 1 lớp học trong trường thì khó hơn là thêm 1 chỗ ngồi cho 1 sinh viên trong lớp. Khi thêm 1 lớp học thì phải đảm bảo đủ số lượng sinh viên để mở lớp, đảm bảo có đủ các trang thiết bị phục vụ cho lớp học đó và còn phải có giờ giấc, lịch học hẳn hoi. Trong khi thêm 1 ghế cho 1 sinh viên vào lớp trễ thì quá dễ dàng.
Ví dụ: trong một lớp học A có 50 sinh viên, có thêm 10 sinh viên đăng kí vào học. Thay vì mở thêm lớp học mới, ta nên đưa 10 bạn đó vào danh sách lớp học A sẽ tiết kiệm được khoảng chi phí mở lớp học mới.
truongtph.i11c- Tổng số bài gửi : 26
Join date : 26/08/2011
Multithreading trong Java (post lên cho bạn nào thích java thì tham khảo)
Multithreading (đa tuyến) trong Java
Multithreading cho phép hai phần của cùng một chương trình chạy đồng thời. Article này thảo luận về cách làm thế nào để thực hiện điều này tốt nhất trong Java. Đây là một phần trích từ chương 10 của cuốn sách Java Dymistyfied, được viết bởi Jim Keogh.
Các vận động viên marathon thường đối mặt với tình trạng khó khăn khi cả hai cuộc đua chính rơi vào trong cùng một tuần bởi vì họ phải chọn một cuộc đua để chạy. Họ chắc chắn phải mong ước có một cách, một phần của họ có thể chạy một cuộc đua và một phần khác chạy một cuộc đua khác. Điều đó không thể xảy ra – đó là ngoại trừ, vận động viên chính là một chương trình Java, bởi vì hai phần của một chương trình Java có thể chạy đồng thời bằng việc sử dụng multithreading. Bạn sẽ học về multithreading và cách làm thế nào để chạy đồng thời các phần của chương trình của bạn trong chương này.
Multitasking (đa nhiệm)
Multitasking thực thi hai hay nhiều tác nhiệm cùng một lúc. Gần như tất cả các hệ điều hành đều có khả năng multitasking bởi việc sử dụng một trong hai kỹ thuật multitasking: multitasking dựa trên process (xử lý) và multitasking dựa trên thread (phân tuyến).
Multitasking dựa trên process chạy hai chương trình cùng một lúc. Các lập trình viên nói đến một chương trình là một process. Vì thế bạn có thể nói rằng, multitasking dựa trên process là multitasking dựa trên chương trình.
Multitasking dựa trên thread có một chương trình thực hiện hai tác nhiệm cùng một thời điểm. Ví dụ, một chương trình xử lý văn bản có thể kiểm tra lỗi chính tả trong một tài liệu trong khi bạn đang viết một tài liệu đó. Đó là multitasking dựa trên thread.
Cách khá tốt để nhớ được sự khác nhau giữa multitasking dựa trên process và multitasking dựa trên thread là hãy nghĩ dựa trên process là làm việc với nhiều chương trình và dựa trên thread là làm việc với nhiều phần của một chương trình.
Mục tiêu của multitasking là sử dụng thời gian nghỉ của CPU. Tưởng tượng rằng CPU là một động cơ trong xe hơi của bạn. Động cơ xe của bạn luôn chạy cho dù xe hơi có di chuyển hay không. Bạn muốn xe hơi di chuyển nhiều đến mức có thể, để bạn có thể chạy được nhiều dặm từ một gallon ga. Một động cơ để không lãng phí ga.
Cùng một khái niệm như thế áp dụng cho CPU của máy tính của bạn. Bạn muốn CPU của bạn xoay vòng để xử lý các lệnh và dữ liệu hơn là chờ một điều gì đó để xử lý. Một CPU xoay vòng là những gì tương tự với sự vận hành của động cơ của bạn.
Có thể khó khăn để tin tưởng, nhưng CPU nghỉ nhiều hơn là nó xử lý trong nhiều máy tính để bàn. Hãy nói rằng, bạn đang sử dụng một trình xử lý văn bản để viết một tài liệu. Trong hầu hết các phần việc, CPU không làm gì cả cho đến khi bạn nhập một ký tự từ bàn phím hoặc di chuyển chuột. Multitasking được thiết kế để sử dụng phần nhỏ của một giây để xử lý các lệnh từ một chương trình khác hoặc từ một phần khác của cùng một chương trình.
Tạo nên sự sử dụng CPU một cách có hiệu quả không phải là quá quyết định đối với các chương trình chạy trên một máy tính để bàn bởi vì hầu hết chúng ta hiếm khi chạy những chương trình đồng thời hoặc chạy nhiều phần của cùng một chương trình vào một thời điểm. Tuy nhiên, những chương trình đó chạy trên môi trường mạng, cần trao đổi xử lý từ nhiều máy tính, thì cần phải tạo ra một thời gian nghỉ hiệu quả của CPU.
Multithreading trong Java – Overhead
Hệ điều hành phải làm những công việc phụ để quản lý multitasking, các lập trình viên gọi công việc phụ này là overhead bởi vì các tài nguyên trong máy tính của bạn được sử dụng để quản lý sự hoạt động của multitasking nhiều hơn là được sử dụng bởi các chương trình để xử lý các lệnh và dữ liệu. Multitasking dựa trên process có một overhead lớn hơn multitasking dựa trên thread. Trong multitasking dựa trên process, mỗi process yêu cầu không gian địa chỉ của chính nó trong vùng nhớ. Hệ điều hành yêu cầu một lượng thời gian CPU xác định để chuyển từ một xử lý này sang một xử lý khác. Các lập trình viên gọi đây là context switching, ở đó mỗi process (hay chương trình) là một context. Các tài nguyên được bổ sung cần cho mỗi process để giao tiếp với mỗi process khác.
Trong sự so sánh này, các thread trong multitasking dựa trên thread chia sẻ cùng một không gian địa chỉ trong vùng nhớ bởi vì chúng chia sẻ cùng một chương trình. Ở đây cũng có một tác động trong context switching, bởi vì chuyển đổi từ một phần của chương trình sang một phần khác xảy ra trong cùng một không gian địa chỉ của vùng nhớ. Ngược lại, việc giao tiếp giữa các phần của chương trình xảy ra trong cùng một vị trí vùng nhớ.
Thread
Một thread là một phần của chương trình đang chạy. Multitasking dựa trên thread có nhiều thread chạy cùng một thời điểm (nhiều phần của một chương trình chạy cùng một lúc). Mỗi thread là một cách thực thi khác nhau.
Hãy trở về ví dụ trình xử lý văn bản để xem các thread được sử dụng như thế nào. Hai phần của trình xử lý văn bản được quan tâm: đầu tiên là phần nhận các ký tự nhập từ bàn phím, lưu chúng vào bộ nhớ, và hiển thị chúng trên màn hình. Phần thứ hai là phần còn lại của chương trình nhằm kiểm tra chính tả. Mỗi phần là một thread thực thi độc lập với phần khác. Thậm chí dù chúng là cùng một chương trình. Trong khi một thread nhận và xử lý các ký tự được nhập từ bàn phím, thread khác ngủ. Đó là, thread khác dừng cho đến khi CPU nghỉ. CPU thường nghỉ giữa các lần gõ phím. Vào khoảng thời gian này, thread bộ kiểm tra chính tả đang ngủ thức dậy tiếp tục kiểm tra chính tả của tài liệu. Thread bộ kiểm tra chính tả dừng một lần nữa khi ký tự kế tiếp được nhập từ bàn phím.
Môi trường runtime Java quản lý các thread không giống như multitasking dựa trên process mà ở đó hệ điều hành quản lý việc chuyển đổi giữa các chương trình. Các thread được xử lý đồng bộ. Điều đó có nghĩa là một thread có thể dừng trong khi một thread có thể tiếp tục xử lý.
Một thread có thể là một trong bốn trạng thái sau:
Running: một thread đang được thực thi.
Suspended: việc thực thi bị tạm dừng và có thể phục hồi tại thời điểm dừng
Blocked: một tài nguyên không thể được truy cập bởi vì nó đang được sử dụng bởi một thread khác.
Terminated: việc thực thi bị ngừng hẳn và không thể phục hồi.
Tất cả các thread không giống nhau. Một vài thread quan trọng hơn những thread khác và được cho quyền ưu tiên cao hơn đối với các tài nguyên như CPU. Mỗi thread được gán một quyền ưu tiên thread được sử dụng để xác định khi nào thì chuyển từ một thread đang thực thi sang một thread khác. Được gọi là context switching.
Quyền ưu tiên của một thread có quan hệ với quyền ưu tiên của các thread khác. Quyền ưu tiên của một thread là không thích hợp khi chỉ có một mình thread đó đang chạy. Thread có quyền ưu tiên thấp hơn cũng chạy nhanh như thread có quyền ưu tiên cao hơn nếu như không có thread nào khác chạy cùng một lúc.
Các quyền ưu tiên của thread được sử dụng khi các quy luật của context switching được sử dụng. Dưới đây là những quy luật này:
Một thread có thể tự động sản sinh ra một thread khác. Để làm được điều này, điều khiển được trả về cho thread có quyền ưu tiên cao nhất.
Một thread có quyền ưu tiên cao hơn có thể giành quyền sử dụng CPU từ một thread có quyền ưu tiên thấp hơn. Thread có quyền ưu tiên thấp hơn bị tạm dừng bất chấp nó đang làm gì để trả về theo cách của thread có quyền ưu tiên cao hơn. Các lập trình viên gọi đây là preemptive multitasking.
Các thread có quyền ưu tiên bằng nhau được xử lý dựa trên các quy luật của hệ điều hành đang được sử dụng để chạy chương trình. Ví dụ, Windows sử dụng time slicing, bao gồm việc cho mỗi thread có quyền ưu tiên cao một vài mili giây của vòng CPU và giữ việc xoay vòng giữa các thread có quyền ưu tiên cao. Trong Solaris, thread có quyền ưu tiên cao nhất phải tự động sản sinh ra các thread có quyền ưu tiên cao khác. Nếu không, thread có quyền ưu tiên cao thứ nhì phải chờ thread có quyền ưu tiên cao nhất kết thúc.
Sự đồng bộ hoá
Multithreading xảy ra không đồng bộ, có nghĩa là một thread thực thi độc lập với các thread khác. Theo đó, mỗi thread không phụ thuộc vào sự thực thi của các thread khác. Để bắt buộc, các xử lý chạy đồng bộ hóa phụ thuộc vào các xử lý khác. Đó là một xử lý chờ cho đến khi một xử lý khác kết thúc trước khi nó có thể thực thi.
Thỉnh thoảng, việc thực thi của một thread có thể phụ thuộc vào việc thực thi của một thread khác. Giả sử bạn có hai thread – một tập hợp các thông tin đăng nhập và một cái khác kiểm tra mật khẩu và ID của người dùng. Thread login phải chờ thread validation hoàn tất xử lý trước khi nó có thể nói cho người dùng việc đăng nhập có thành công hay không. Vì thế cả hai thread phải được thực thi đồng bộ, không được không đồng bộ.
Java cho phép các thread đồng bộ hóa được định nghĩa bởi một method đồng bộ hoá. Một thread nằm trong một method đồng bộ hóa ngăn bất kỳ thread nào khác từ một phương thức đồng bộ hoá khác gọi trong cùng một đối tượng. Bạn sẽ học chúng trong phần sau của chương này.
Multithreading cho phép hai phần của cùng một chương trình chạy đồng thời. Article này thảo luận về cách làm thế nào để thực hiện điều này tốt nhất trong Java. Đây là một phần trích từ chương 10 của cuốn sách Java Dymistyfied, được viết bởi Jim Keogh.
Các vận động viên marathon thường đối mặt với tình trạng khó khăn khi cả hai cuộc đua chính rơi vào trong cùng một tuần bởi vì họ phải chọn một cuộc đua để chạy. Họ chắc chắn phải mong ước có một cách, một phần của họ có thể chạy một cuộc đua và một phần khác chạy một cuộc đua khác. Điều đó không thể xảy ra – đó là ngoại trừ, vận động viên chính là một chương trình Java, bởi vì hai phần của một chương trình Java có thể chạy đồng thời bằng việc sử dụng multithreading. Bạn sẽ học về multithreading và cách làm thế nào để chạy đồng thời các phần của chương trình của bạn trong chương này.
Multitasking (đa nhiệm)
Multitasking thực thi hai hay nhiều tác nhiệm cùng một lúc. Gần như tất cả các hệ điều hành đều có khả năng multitasking bởi việc sử dụng một trong hai kỹ thuật multitasking: multitasking dựa trên process (xử lý) và multitasking dựa trên thread (phân tuyến).
Multitasking dựa trên process chạy hai chương trình cùng một lúc. Các lập trình viên nói đến một chương trình là một process. Vì thế bạn có thể nói rằng, multitasking dựa trên process là multitasking dựa trên chương trình.
Multitasking dựa trên thread có một chương trình thực hiện hai tác nhiệm cùng một thời điểm. Ví dụ, một chương trình xử lý văn bản có thể kiểm tra lỗi chính tả trong một tài liệu trong khi bạn đang viết một tài liệu đó. Đó là multitasking dựa trên thread.
Cách khá tốt để nhớ được sự khác nhau giữa multitasking dựa trên process và multitasking dựa trên thread là hãy nghĩ dựa trên process là làm việc với nhiều chương trình và dựa trên thread là làm việc với nhiều phần của một chương trình.
Mục tiêu của multitasking là sử dụng thời gian nghỉ của CPU. Tưởng tượng rằng CPU là một động cơ trong xe hơi của bạn. Động cơ xe của bạn luôn chạy cho dù xe hơi có di chuyển hay không. Bạn muốn xe hơi di chuyển nhiều đến mức có thể, để bạn có thể chạy được nhiều dặm từ một gallon ga. Một động cơ để không lãng phí ga.
Cùng một khái niệm như thế áp dụng cho CPU của máy tính của bạn. Bạn muốn CPU của bạn xoay vòng để xử lý các lệnh và dữ liệu hơn là chờ một điều gì đó để xử lý. Một CPU xoay vòng là những gì tương tự với sự vận hành của động cơ của bạn.
Có thể khó khăn để tin tưởng, nhưng CPU nghỉ nhiều hơn là nó xử lý trong nhiều máy tính để bàn. Hãy nói rằng, bạn đang sử dụng một trình xử lý văn bản để viết một tài liệu. Trong hầu hết các phần việc, CPU không làm gì cả cho đến khi bạn nhập một ký tự từ bàn phím hoặc di chuyển chuột. Multitasking được thiết kế để sử dụng phần nhỏ của một giây để xử lý các lệnh từ một chương trình khác hoặc từ một phần khác của cùng một chương trình.
Tạo nên sự sử dụng CPU một cách có hiệu quả không phải là quá quyết định đối với các chương trình chạy trên một máy tính để bàn bởi vì hầu hết chúng ta hiếm khi chạy những chương trình đồng thời hoặc chạy nhiều phần của cùng một chương trình vào một thời điểm. Tuy nhiên, những chương trình đó chạy trên môi trường mạng, cần trao đổi xử lý từ nhiều máy tính, thì cần phải tạo ra một thời gian nghỉ hiệu quả của CPU.
Multithreading trong Java – Overhead
Hệ điều hành phải làm những công việc phụ để quản lý multitasking, các lập trình viên gọi công việc phụ này là overhead bởi vì các tài nguyên trong máy tính của bạn được sử dụng để quản lý sự hoạt động của multitasking nhiều hơn là được sử dụng bởi các chương trình để xử lý các lệnh và dữ liệu. Multitasking dựa trên process có một overhead lớn hơn multitasking dựa trên thread. Trong multitasking dựa trên process, mỗi process yêu cầu không gian địa chỉ của chính nó trong vùng nhớ. Hệ điều hành yêu cầu một lượng thời gian CPU xác định để chuyển từ một xử lý này sang một xử lý khác. Các lập trình viên gọi đây là context switching, ở đó mỗi process (hay chương trình) là một context. Các tài nguyên được bổ sung cần cho mỗi process để giao tiếp với mỗi process khác.
Trong sự so sánh này, các thread trong multitasking dựa trên thread chia sẻ cùng một không gian địa chỉ trong vùng nhớ bởi vì chúng chia sẻ cùng một chương trình. Ở đây cũng có một tác động trong context switching, bởi vì chuyển đổi từ một phần của chương trình sang một phần khác xảy ra trong cùng một không gian địa chỉ của vùng nhớ. Ngược lại, việc giao tiếp giữa các phần của chương trình xảy ra trong cùng một vị trí vùng nhớ.
Thread
Một thread là một phần của chương trình đang chạy. Multitasking dựa trên thread có nhiều thread chạy cùng một thời điểm (nhiều phần của một chương trình chạy cùng một lúc). Mỗi thread là một cách thực thi khác nhau.
Hãy trở về ví dụ trình xử lý văn bản để xem các thread được sử dụng như thế nào. Hai phần của trình xử lý văn bản được quan tâm: đầu tiên là phần nhận các ký tự nhập từ bàn phím, lưu chúng vào bộ nhớ, và hiển thị chúng trên màn hình. Phần thứ hai là phần còn lại của chương trình nhằm kiểm tra chính tả. Mỗi phần là một thread thực thi độc lập với phần khác. Thậm chí dù chúng là cùng một chương trình. Trong khi một thread nhận và xử lý các ký tự được nhập từ bàn phím, thread khác ngủ. Đó là, thread khác dừng cho đến khi CPU nghỉ. CPU thường nghỉ giữa các lần gõ phím. Vào khoảng thời gian này, thread bộ kiểm tra chính tả đang ngủ thức dậy tiếp tục kiểm tra chính tả của tài liệu. Thread bộ kiểm tra chính tả dừng một lần nữa khi ký tự kế tiếp được nhập từ bàn phím.
Môi trường runtime Java quản lý các thread không giống như multitasking dựa trên process mà ở đó hệ điều hành quản lý việc chuyển đổi giữa các chương trình. Các thread được xử lý đồng bộ. Điều đó có nghĩa là một thread có thể dừng trong khi một thread có thể tiếp tục xử lý.
Một thread có thể là một trong bốn trạng thái sau:
Running: một thread đang được thực thi.
Suspended: việc thực thi bị tạm dừng và có thể phục hồi tại thời điểm dừng
Blocked: một tài nguyên không thể được truy cập bởi vì nó đang được sử dụng bởi một thread khác.
Terminated: việc thực thi bị ngừng hẳn và không thể phục hồi.
Tất cả các thread không giống nhau. Một vài thread quan trọng hơn những thread khác và được cho quyền ưu tiên cao hơn đối với các tài nguyên như CPU. Mỗi thread được gán một quyền ưu tiên thread được sử dụng để xác định khi nào thì chuyển từ một thread đang thực thi sang một thread khác. Được gọi là context switching.
Quyền ưu tiên của một thread có quan hệ với quyền ưu tiên của các thread khác. Quyền ưu tiên của một thread là không thích hợp khi chỉ có một mình thread đó đang chạy. Thread có quyền ưu tiên thấp hơn cũng chạy nhanh như thread có quyền ưu tiên cao hơn nếu như không có thread nào khác chạy cùng một lúc.
Các quyền ưu tiên của thread được sử dụng khi các quy luật của context switching được sử dụng. Dưới đây là những quy luật này:
Một thread có thể tự động sản sinh ra một thread khác. Để làm được điều này, điều khiển được trả về cho thread có quyền ưu tiên cao nhất.
Một thread có quyền ưu tiên cao hơn có thể giành quyền sử dụng CPU từ một thread có quyền ưu tiên thấp hơn. Thread có quyền ưu tiên thấp hơn bị tạm dừng bất chấp nó đang làm gì để trả về theo cách của thread có quyền ưu tiên cao hơn. Các lập trình viên gọi đây là preemptive multitasking.
Các thread có quyền ưu tiên bằng nhau được xử lý dựa trên các quy luật của hệ điều hành đang được sử dụng để chạy chương trình. Ví dụ, Windows sử dụng time slicing, bao gồm việc cho mỗi thread có quyền ưu tiên cao một vài mili giây của vòng CPU và giữ việc xoay vòng giữa các thread có quyền ưu tiên cao. Trong Solaris, thread có quyền ưu tiên cao nhất phải tự động sản sinh ra các thread có quyền ưu tiên cao khác. Nếu không, thread có quyền ưu tiên cao thứ nhì phải chờ thread có quyền ưu tiên cao nhất kết thúc.
Sự đồng bộ hoá
Multithreading xảy ra không đồng bộ, có nghĩa là một thread thực thi độc lập với các thread khác. Theo đó, mỗi thread không phụ thuộc vào sự thực thi của các thread khác. Để bắt buộc, các xử lý chạy đồng bộ hóa phụ thuộc vào các xử lý khác. Đó là một xử lý chờ cho đến khi một xử lý khác kết thúc trước khi nó có thể thực thi.
Thỉnh thoảng, việc thực thi của một thread có thể phụ thuộc vào việc thực thi của một thread khác. Giả sử bạn có hai thread – một tập hợp các thông tin đăng nhập và một cái khác kiểm tra mật khẩu và ID của người dùng. Thread login phải chờ thread validation hoàn tất xử lý trước khi nó có thể nói cho người dùng việc đăng nhập có thành công hay không. Vì thế cả hai thread phải được thực thi đồng bộ, không được không đồng bộ.
Java cho phép các thread đồng bộ hóa được định nghĩa bởi một method đồng bộ hoá. Một thread nằm trong một method đồng bộ hóa ngăn bất kỳ thread nào khác từ một phương thức đồng bộ hoá khác gọi trong cùng một đối tượng. Bạn sẽ học chúng trong phần sau của chương này.
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Multithreading trong Java (tiếp theo)
Interface (giao tiếp) Runnable và các lớp Thread
Bạn khởi dựng các thread bằng việc sử dụng interface Runnable và class Thread. Điều này có nghĩa là thread của bạn phải kế thừa từ class Thread hoặc bổ sung interface Runnable. Class Thread định nghĩa bên trong các method bạn sử dụng để quản lý thread. Dưới đây là các method thông dụng được định nghĩa trong class Thread.
Method
Mô tả
getName()
Trả về tên của thread
getPriority()
Trả về quyền ưu tiên của thread.
isAlive()
Xác định thread nào đang chạy
join()
Tạm dừng cho đến khi thread kết thúc
run()
Danh mục cần thực hiện bên trong thread
sleep()
Suspends một thread. Method này cho phép bạn xác định khoảng thời gian mà thread được cho tạm dừng
start()
Bắt đầu thread.
Main thread
Mỗi chương trình Java có một thread, thậm chí nếu bạn không tạo ra bất kỳ thread nào. Thread này được gọi là main thread bởi vì nó là thread thực thi khi bạn bắt đầu chương trình của bạn. Main thread sinh ra các thread mà bạn tạo ra. Những thread đó gọi là child thread. Main thread luôn luôn là thread cuối cùng kết thúc việc thực thi bởi vì thông thường main thread cần giải phóng tài nguyên được sử dụng bởi chương trình chẳng hạn như các kết nối mạng.
Các lập trình viên có thể điều khiển main thread bằng cách đầu tiên tạo ra một đối tượng thread và sau đó sử dụng các method của đối tượng thread để điều khiển main thread. Bạn tạo đối tượng thread bằng cách gọi method currentThread(). Method currentThread() trả về một reference (tham chiếu) đến thread, sau đó bạn sử dụng reference này để điều khiển main thread như bất kỳ thread nào khác. Để tạo một reference đến main thread và đổi tên của thread từ main thành Demo Thread. Chương trình dưới đây chỉ ra làm thế nào để làm được điều này. Màn hình hiển thị khi chương trình chạy
Current thread: Thread[main, 5,main]
Renamed Thread: Thread[Demo Thread, 5,main]
Đoạn mã dưới đây sẽ thể hiện điều đó.
class Demo {
public static void main (String args[] ) {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);
t.setName("Demo Thread");
System.out.println("Renamed Thread: " + t);
}
}
Như bạn đã học trong chương này, một thread tự động được tạo ra khi bạn thực thi một chương trình. Mục đích của ví dụ này là công bố một reference đến một thread và gán nó cho main thread. Điều này được thực hiện trong dòng đầu tiên của method main(). Chúng ta công bố reference bằng việc xác định tên của lớp và tên cho reference. Điều này được thực hiện nhờ dòng mã Thread t = Thread.currentThread()
Chúng ta có được một reference đến main thread bằng việc gọi method currentThread() của class Thread. Reference trả về bởi method currentThread() sau đó được gán cho reference được công bố trước đó trong phần mở đầu phát biểu.
Thread[main, 5,main]
Thông tin bên trong cặp ngoặc vuông nói cho chúng ta biết vài thông tin về thread. Từ main xuất hiện đầu tiên là tên của thread. Số 5 là quyền ưu tiên của thread, là quyền ưu tiên thông thường. Quyền ưu tiên nằm trong phạm vi từ 1 đến 10, trong đó 1 là thấp nhất và 10 là cao nhất. Từ main nằm cuối cùng là tên của nhóm thread mà thread đó thuộc về. Một nhóm các thead là một cấu trúc dữ liệu được sử dụng để điều khiển trạng thái của một tập hợp các thread. Bạn không cần quan tâm đến nhóm thread bởi vì môi trường Java run-time xử lý điều này.
Method setName() được gọi chỉ ra làm thế nào để bạn điều khiển main thread của chương trình của bạn.Method setName() là một method thành viên của class Thread và được sử dụng để thay đổi tên của một thread. Ví dụ này sử dụng setName() để thay đổi tên của main thread từ main thành Demo Thread. Thread hiển thị một lần nữa trên màn hình với tên đã được thay đổi.
Tạo các thread của riêng bạn
Nhớ rằng chương trình của bạn là main thread, và các phần khác của chương trình của bạn có thể cũng là một thread. Bạn có thể thiết kế một phần của chương trình của bạn là thread bằng việc tạo ra thread của riêng bạn. Cách dễ dàng nhất để làm điều này là bổ sung interface Runnable. Việc bổ sung interface Runnable là một lựa chọn để các lớp của bạn kế thừa class Thread.
Một interface mô tả một hay nhiều method thành viên mà bạn phải định nghĩa trong class của bạn theo quy định tuân theo interface. Những method này được mô tả với tên method, danh sách đối số và giá trị trả về.
Interface Runnable mô tả các method của lớp cần tạo và tương tác với một thread. Theo quy định, để sử dụng interface trong class của bạn, bạn phải định nghĩa các method được mô tả trong interface Runnable. Khá thuận lợi, bạn chỉ cần định nghĩa một method được mô tả bởi interface Runnable – method run(). Method run() phải là một method public, và nó không yêu cầu danh sách đối số cũng như giá trị trả về.
Nội dung của method run() là một phần của chương trình bạn sẽ trở thành một thread mới. Các phát biểu bên ngoài method run() là thuộc về main thread. Các phát biểu bên trong method run() thuộc về thread mới. Cả main thread và thread mới chạy cùng một lúc khi bạn bắt đầu thread mới. Bạn sẽ học điều này trong ví dụ kế tiếp. Thread mới kết thúc khi method run() kết thúc. Điều khiển sau đó trả về cho phát biểu gọi method run().
Khi bạn bổ sung interface Runnable, bạn sẽ cần gọi khởi dựng dưới đây của class Thread. Khởi dựng này yêu cầu hai đối số. Đối số đầu tiên là thực thể của lớp để bổ sung interface Runnable và nói cho khởi dựng biết thread được thực thi từ đâu. Đối số thứ hai là tên của thread mới. Đây là định dạng của khởi dựng
Thread(Runnable class, String name)
Khởi dựng tạo ra một thread mới nhưng nó không bắt đầu thread. Bạn bắt đầu thread bằng cách gọi method start(). Method start() gọi method run() bạn định nghĩa trong chương trình của bạn. Method start() không có danh sách đối số và không có giá trị trả về. Ví dụ dưới đây chỉ ra làm thế nào để tạo ra và bắt đầu một thread mới. Đây là những gì hiển thị khi chương trình chạy.
Main thread started
Child thread started
Child thread terminated
Main thread terminated
class MyThread implements Runnable {
Thread t;
MyThread() {
t = new Thread(this,"My thread");
t.start();
}
public void run() {
System.out.println("Child thread started");
System.out.println("Child thread terminated");
}
}
class Demo {
public static void main(String args[]) {
new MyThread();
System.out.println("Main thread started");
System.out.println("Main thread terminated");
}
}
Ví dụ này bắt đầu bằng việc định nghĩa một class gọi là MyThread, bổ sung interface Runnable. Vì thế chúng ta sử dụng từ khóa implements để bổ sung interface Runnable. Kế tiếp, một reference đến thread được công bố. Tiếp đó là định nghĩa khởi dựng cho class. Khởi dựng này gọi khởi dựng của class Thread. Bởi vì chúng ta bổ sung interface Runnable, chúng ta cần đặt khởi dựng reference đến thực thể của class sẽ thực thi thread mới và tên của thread mới. Chú ý rằng, từ khóa this là một reference đến thực thể hiện hành của class.
Khởi dựng trả về một reference cho thread mới, và được gán cho reference được công bố ở phát biểu đầu tiên trong class MyThread. Chúng ta sử dụng reference này để gọi method start(). Nhớ rằng method start() gọi method run()
Kế đến chúng ta định nghĩa method run(). Những phát biểu bên trong method run() trở thành một phần của chương trình thực thi khi thread thực thi. Chỉ có hai phát biểu thể hiện trong method run().
Kế tiếp, chúng ta định nghĩa class chương trình. Class chương trình thực thi thread mới bằng việc gọi thực thể của class MyThread. Thực hiện điều này bằng cách gọi toán tử new và khởi dựng của class MyThread.
Cuối cùng chương trình kết thúc bằng việc hiển thị hai dòng trên màn hình. [b]
Bạn khởi dựng các thread bằng việc sử dụng interface Runnable và class Thread. Điều này có nghĩa là thread của bạn phải kế thừa từ class Thread hoặc bổ sung interface Runnable. Class Thread định nghĩa bên trong các method bạn sử dụng để quản lý thread. Dưới đây là các method thông dụng được định nghĩa trong class Thread.
Method
Mô tả
getName()
Trả về tên của thread
getPriority()
Trả về quyền ưu tiên của thread.
isAlive()
Xác định thread nào đang chạy
join()
Tạm dừng cho đến khi thread kết thúc
run()
Danh mục cần thực hiện bên trong thread
sleep()
Suspends một thread. Method này cho phép bạn xác định khoảng thời gian mà thread được cho tạm dừng
start()
Bắt đầu thread.
Main thread
Mỗi chương trình Java có một thread, thậm chí nếu bạn không tạo ra bất kỳ thread nào. Thread này được gọi là main thread bởi vì nó là thread thực thi khi bạn bắt đầu chương trình của bạn. Main thread sinh ra các thread mà bạn tạo ra. Những thread đó gọi là child thread. Main thread luôn luôn là thread cuối cùng kết thúc việc thực thi bởi vì thông thường main thread cần giải phóng tài nguyên được sử dụng bởi chương trình chẳng hạn như các kết nối mạng.
Các lập trình viên có thể điều khiển main thread bằng cách đầu tiên tạo ra một đối tượng thread và sau đó sử dụng các method của đối tượng thread để điều khiển main thread. Bạn tạo đối tượng thread bằng cách gọi method currentThread(). Method currentThread() trả về một reference (tham chiếu) đến thread, sau đó bạn sử dụng reference này để điều khiển main thread như bất kỳ thread nào khác. Để tạo một reference đến main thread và đổi tên của thread từ main thành Demo Thread. Chương trình dưới đây chỉ ra làm thế nào để làm được điều này. Màn hình hiển thị khi chương trình chạy
Current thread: Thread[main, 5,main]
Renamed Thread: Thread[Demo Thread, 5,main]
Đoạn mã dưới đây sẽ thể hiện điều đó.
class Demo {
public static void main (String args[] ) {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);
t.setName("Demo Thread");
System.out.println("Renamed Thread: " + t);
}
}
Như bạn đã học trong chương này, một thread tự động được tạo ra khi bạn thực thi một chương trình. Mục đích của ví dụ này là công bố một reference đến một thread và gán nó cho main thread. Điều này được thực hiện trong dòng đầu tiên của method main(). Chúng ta công bố reference bằng việc xác định tên của lớp và tên cho reference. Điều này được thực hiện nhờ dòng mã Thread t = Thread.currentThread()
Chúng ta có được một reference đến main thread bằng việc gọi method currentThread() của class Thread. Reference trả về bởi method currentThread() sau đó được gán cho reference được công bố trước đó trong phần mở đầu phát biểu.
Thread[main, 5,main]
Thông tin bên trong cặp ngoặc vuông nói cho chúng ta biết vài thông tin về thread. Từ main xuất hiện đầu tiên là tên của thread. Số 5 là quyền ưu tiên của thread, là quyền ưu tiên thông thường. Quyền ưu tiên nằm trong phạm vi từ 1 đến 10, trong đó 1 là thấp nhất và 10 là cao nhất. Từ main nằm cuối cùng là tên của nhóm thread mà thread đó thuộc về. Một nhóm các thead là một cấu trúc dữ liệu được sử dụng để điều khiển trạng thái của một tập hợp các thread. Bạn không cần quan tâm đến nhóm thread bởi vì môi trường Java run-time xử lý điều này.
Method setName() được gọi chỉ ra làm thế nào để bạn điều khiển main thread của chương trình của bạn.Method setName() là một method thành viên của class Thread và được sử dụng để thay đổi tên của một thread. Ví dụ này sử dụng setName() để thay đổi tên của main thread từ main thành Demo Thread. Thread hiển thị một lần nữa trên màn hình với tên đã được thay đổi.
Tạo các thread của riêng bạn
Nhớ rằng chương trình của bạn là main thread, và các phần khác của chương trình của bạn có thể cũng là một thread. Bạn có thể thiết kế một phần của chương trình của bạn là thread bằng việc tạo ra thread của riêng bạn. Cách dễ dàng nhất để làm điều này là bổ sung interface Runnable. Việc bổ sung interface Runnable là một lựa chọn để các lớp của bạn kế thừa class Thread.
Một interface mô tả một hay nhiều method thành viên mà bạn phải định nghĩa trong class của bạn theo quy định tuân theo interface. Những method này được mô tả với tên method, danh sách đối số và giá trị trả về.
Interface Runnable mô tả các method của lớp cần tạo và tương tác với một thread. Theo quy định, để sử dụng interface trong class của bạn, bạn phải định nghĩa các method được mô tả trong interface Runnable. Khá thuận lợi, bạn chỉ cần định nghĩa một method được mô tả bởi interface Runnable – method run(). Method run() phải là một method public, và nó không yêu cầu danh sách đối số cũng như giá trị trả về.
Nội dung của method run() là một phần của chương trình bạn sẽ trở thành một thread mới. Các phát biểu bên ngoài method run() là thuộc về main thread. Các phát biểu bên trong method run() thuộc về thread mới. Cả main thread và thread mới chạy cùng một lúc khi bạn bắt đầu thread mới. Bạn sẽ học điều này trong ví dụ kế tiếp. Thread mới kết thúc khi method run() kết thúc. Điều khiển sau đó trả về cho phát biểu gọi method run().
Khi bạn bổ sung interface Runnable, bạn sẽ cần gọi khởi dựng dưới đây của class Thread. Khởi dựng này yêu cầu hai đối số. Đối số đầu tiên là thực thể của lớp để bổ sung interface Runnable và nói cho khởi dựng biết thread được thực thi từ đâu. Đối số thứ hai là tên của thread mới. Đây là định dạng của khởi dựng
Thread(Runnable class, String name)
Khởi dựng tạo ra một thread mới nhưng nó không bắt đầu thread. Bạn bắt đầu thread bằng cách gọi method start(). Method start() gọi method run() bạn định nghĩa trong chương trình của bạn. Method start() không có danh sách đối số và không có giá trị trả về. Ví dụ dưới đây chỉ ra làm thế nào để tạo ra và bắt đầu một thread mới. Đây là những gì hiển thị khi chương trình chạy.
Main thread started
Child thread started
Child thread terminated
Main thread terminated
class MyThread implements Runnable {
Thread t;
MyThread() {
t = new Thread(this,"My thread");
t.start();
}
public void run() {
System.out.println("Child thread started");
System.out.println("Child thread terminated");
}
}
class Demo {
public static void main(String args[]) {
new MyThread();
System.out.println("Main thread started");
System.out.println("Main thread terminated");
}
}
Ví dụ này bắt đầu bằng việc định nghĩa một class gọi là MyThread, bổ sung interface Runnable. Vì thế chúng ta sử dụng từ khóa implements để bổ sung interface Runnable. Kế tiếp, một reference đến thread được công bố. Tiếp đó là định nghĩa khởi dựng cho class. Khởi dựng này gọi khởi dựng của class Thread. Bởi vì chúng ta bổ sung interface Runnable, chúng ta cần đặt khởi dựng reference đến thực thể của class sẽ thực thi thread mới và tên của thread mới. Chú ý rằng, từ khóa this là một reference đến thực thể hiện hành của class.
Khởi dựng trả về một reference cho thread mới, và được gán cho reference được công bố ở phát biểu đầu tiên trong class MyThread. Chúng ta sử dụng reference này để gọi method start(). Nhớ rằng method start() gọi method run()
Kế đến chúng ta định nghĩa method run(). Những phát biểu bên trong method run() trở thành một phần của chương trình thực thi khi thread thực thi. Chỉ có hai phát biểu thể hiện trong method run().
Kế tiếp, chúng ta định nghĩa class chương trình. Class chương trình thực thi thread mới bằng việc gọi thực thể của class MyThread. Thực hiện điều này bằng cách gọi toán tử new và khởi dựng của class MyThread.
Cuối cùng chương trình kết thúc bằng việc hiển thị hai dòng trên màn hình. [b]
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Multithreading trong Java (tiếp theo)
Mã nguồn của ví dụ:
PHP Code:
class MyThread implements Runnable {
String tName;
Thread t;
MyThread (String threadName) {
tName = threadName;
t = new Thread (this, tName);
t.start();
}
public void run() {
try {
System.out.println("Thread: " + tName );
Thread.sleep(2000);
} catch (InterruptedException e ) {
System.out.println("Exception: Thread "
+ tName + " interrupted");
}
System.out.println("Terminating thread: " + tName );
}
}
class Demo {
public static void main (String args []) {
new MyThread ("1");
new MyThread ("2");
new MyThread ("3");
new MyThread ("4");
try {
Thread.sleep (10000);
} catch (InterruptedException e) {
System.out.println("Exception: Thread main interrupted.");
}
System.out.println("Terminating thread: main thread.");
}
}
Sử dụng isAlive() và join()
Thông thường, main thread là thread cuối cùng kết thúc trong một chương trình. Tuy nhiên, không phải là bảo đảm không có những trường hợp, main thread sẽ kết thúc trước khi một child thread kết thúc. Trong ví dụ trước, chúng tôi đã nói method main ngủ cho đến khi các child thread kết thúc. Tuy nhiên chúng tôi đã ước lượng khoảng thời gian nó thực hiện để các child thread hoàn tất xử lý. Nếu khoảng thời gian ước lượng quá ngắn, một child thread có thể kết thúc sau khi main thread đã kết thúc. Vì thế, kỹ thuật sleep không phải là cách tốt nhất để bảo đảm rằng main thread kết thúc cuối cùng.
Các lập trình viên sử dụng hai cách khác để xác định rằng main thread là thread cuối cùng kết thúc. Những kỹ thuật này bao gồm việc gọi method isAlive() và method join(). Cả hai method này đều được định nghĩa trong class Thread.
Method isAlive() xác định còn method nào đang chạy hay không. Nếu còn, isAlive() trả về giá trị Boolean true. Ngược lại, Boolean false được trả về. Bạn sử dụng method isAlive() để xác định còn child method nào tiếp tục chạy hay không. Method join() chờ cho đến khi child thread kết thúc và “kết nối” main thread. Ngoài ra, bạn có thể sử dụng method join() để xác định lượng thời gian mà bạn muốn chờ một child thread kết thúc.
Ví dụ dưới đây chỉ ra sử dụng method isAlive() và method join() trong chương trình của bạn như thế nào. Ví dụ này gần giống ví dụ trước. Sự khác biết nằm ở method main() của class Demo.
Sau khi các thread được công bố sử dụng khởi dựng của class MyThread. Method isAlive() được gọi cho mỗi thread. Giá trị trả về của method isAlive() được hiển thị trên màn hình. Kế tiếp method join() được gọi cho mỗi thread. Method join() làm cho main thread chờ tất cả các child thread hoàn tất xử lý trước khi main thread kết thúc. Đây là những gì hiển thị trên màn hình khi chương trình chạy.
Thread Status: Alive
Thread 1: true
Thread 2: true
Thread 3: true
Thread 4: true
Threads Joining.
Thread: 1
Thread: 2
Thread: 3
Thread: 4
Terminating thread: 1
Terminating thread: 2
Terminating thread: 3
Terminating thread: 4
Thread Status: Alive
Thread 1: false
Thread 2: false
Thread 3: false
Thread 4: false
Terminating thread: main thread.
Mã nguồn
PHP Code:
class MyThread implements Runnable {
String tName;
Thread t;
MyThread (String threadName) {
tName = threadName;
t = new Thread (this, tName);
t.start();
}
public void run() {
try {
System.out.println("Thread: " + tName );
Thread.sleep(2000);
} catch (InterruptedException e ) {
System.out.println("Exception: Thread "
+ tName + " interrupted");
}
System.out.println("Terminating thread: " + tName );
}
}
class Demo {
public static void main (String args []) {
MyThread thread1 = new MyThread ("1");
MyThread thread2 = new MyThread ("2");
MyThread thread3 = new MyThread ("3");
MyThread thread4 = new MyThread ("4");
System.out.println("Thread Status: Alive");
System.out.println("Thread 1: " + thread1.t.isAlive());
System.out.println("Thread 2: " + thread2.t.isAlive());
System.out.println("Thread 3: " + thread3.t.isAlive());
System.out.println("Thread 4: " + thread4.t.isAlive());
try {
System.out.println("Threads Joining.");
thread1.t.join();
thread2.t.join();
thread3.t.join();
thread4.t.join();
} catch (InterruptedException e) {
System.out.println("Exception: Thread main interrupted.");
}
System.out.println("Thread Status: Alive");
System.out.println("Thread 1: " + thread1.t.isAlive());
System.out.println("Thread 2: " + thread2.t.isAlive());
System.out.println("Thread 3: " + thread3.t.isAlive());
System.out.println("Thread 4: " + thread4.t.isAlive());
System.out.println("Terminating thread: main thread.");
}
}
PHP Code:
class MyThread implements Runnable {
String tName;
Thread t;
MyThread (String threadName) {
tName = threadName;
t = new Thread (this, tName);
t.start();
}
public void run() {
try {
System.out.println("Thread: " + tName );
Thread.sleep(2000);
} catch (InterruptedException e ) {
System.out.println("Exception: Thread "
+ tName + " interrupted");
}
System.out.println("Terminating thread: " + tName );
}
}
class Demo {
public static void main (String args []) {
new MyThread ("1");
new MyThread ("2");
new MyThread ("3");
new MyThread ("4");
try {
Thread.sleep (10000);
} catch (InterruptedException e) {
System.out.println("Exception: Thread main interrupted.");
}
System.out.println("Terminating thread: main thread.");
}
}
Sử dụng isAlive() và join()
Thông thường, main thread là thread cuối cùng kết thúc trong một chương trình. Tuy nhiên, không phải là bảo đảm không có những trường hợp, main thread sẽ kết thúc trước khi một child thread kết thúc. Trong ví dụ trước, chúng tôi đã nói method main ngủ cho đến khi các child thread kết thúc. Tuy nhiên chúng tôi đã ước lượng khoảng thời gian nó thực hiện để các child thread hoàn tất xử lý. Nếu khoảng thời gian ước lượng quá ngắn, một child thread có thể kết thúc sau khi main thread đã kết thúc. Vì thế, kỹ thuật sleep không phải là cách tốt nhất để bảo đảm rằng main thread kết thúc cuối cùng.
Các lập trình viên sử dụng hai cách khác để xác định rằng main thread là thread cuối cùng kết thúc. Những kỹ thuật này bao gồm việc gọi method isAlive() và method join(). Cả hai method này đều được định nghĩa trong class Thread.
Method isAlive() xác định còn method nào đang chạy hay không. Nếu còn, isAlive() trả về giá trị Boolean true. Ngược lại, Boolean false được trả về. Bạn sử dụng method isAlive() để xác định còn child method nào tiếp tục chạy hay không. Method join() chờ cho đến khi child thread kết thúc và “kết nối” main thread. Ngoài ra, bạn có thể sử dụng method join() để xác định lượng thời gian mà bạn muốn chờ một child thread kết thúc.
Ví dụ dưới đây chỉ ra sử dụng method isAlive() và method join() trong chương trình của bạn như thế nào. Ví dụ này gần giống ví dụ trước. Sự khác biết nằm ở method main() của class Demo.
Sau khi các thread được công bố sử dụng khởi dựng của class MyThread. Method isAlive() được gọi cho mỗi thread. Giá trị trả về của method isAlive() được hiển thị trên màn hình. Kế tiếp method join() được gọi cho mỗi thread. Method join() làm cho main thread chờ tất cả các child thread hoàn tất xử lý trước khi main thread kết thúc. Đây là những gì hiển thị trên màn hình khi chương trình chạy.
Thread Status: Alive
Thread 1: true
Thread 2: true
Thread 3: true
Thread 4: true
Threads Joining.
Thread: 1
Thread: 2
Thread: 3
Thread: 4
Terminating thread: 1
Terminating thread: 2
Terminating thread: 3
Terminating thread: 4
Thread Status: Alive
Thread 1: false
Thread 2: false
Thread 3: false
Thread 4: false
Terminating thread: main thread.
Mã nguồn
PHP Code:
class MyThread implements Runnable {
String tName;
Thread t;
MyThread (String threadName) {
tName = threadName;
t = new Thread (this, tName);
t.start();
}
public void run() {
try {
System.out.println("Thread: " + tName );
Thread.sleep(2000);
} catch (InterruptedException e ) {
System.out.println("Exception: Thread "
+ tName + " interrupted");
}
System.out.println("Terminating thread: " + tName );
}
}
class Demo {
public static void main (String args []) {
MyThread thread1 = new MyThread ("1");
MyThread thread2 = new MyThread ("2");
MyThread thread3 = new MyThread ("3");
MyThread thread4 = new MyThread ("4");
System.out.println("Thread Status: Alive");
System.out.println("Thread 1: " + thread1.t.isAlive());
System.out.println("Thread 2: " + thread2.t.isAlive());
System.out.println("Thread 3: " + thread3.t.isAlive());
System.out.println("Thread 4: " + thread4.t.isAlive());
try {
System.out.println("Threads Joining.");
thread1.t.join();
thread2.t.join();
thread3.t.join();
thread4.t.join();
} catch (InterruptedException e) {
System.out.println("Exception: Thread main interrupted.");
}
System.out.println("Thread Status: Alive");
System.out.println("Thread 1: " + thread1.t.isAlive());
System.out.println("Thread 2: " + thread2.t.isAlive());
System.out.println("Thread 3: " + thread3.t.isAlive());
System.out.println("Thread 4: " + thread4.t.isAlive());
System.out.println("Terminating thread: main thread.");
}
}
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Multithreading trong Java (tiếp theo)
Cài đặt quyền ưu tiên của Thread
Trong phần trước, bạn đã học được mỗi thread có một quyền ưu tiên được gán được sử dụng những thread quan trọng hơn sử dụng tài nguyên. Quyền ưu tiên được sử dụng như một hướng dẫn cho hệ điều hành xác định được thread nào được truy cập đến một tài nguyên chẳng hạn như CPU. Trong thực tế, hệ điều hành đặt các trình quản lý vào trong sự quản lý của nó. Thông thường các lập trình viên có một ít hoặc không có quyền điều khiển đối với những trình quản lý khác. Vì thế, chúng thành lập quyền ưu tiên cho các thread của chúng mà không quan tâm xa hơn đến những trình quản lý khác.
Một quyền ưu tiên là một số nguyên chính xác từ 1 đến 10, trong đó 10 là quyền ưu tiên cao nhất được xem như quyền ưu tiên tối đa, và 1 là quyền ưu tiên thấp nhất được xem như quyền ưu tiên tối thiểu. Quyền ưu tiên thông thường là 5, là quyền ưu tiên mặc định cho mỗi thread.
Nói chung, một thread có quyền ưu tiên cao hơn giành việc sử dụng tài nguyên của thread có quyền ưu tiên thấp hơn. Thread có quyền ưu tiên thấp hơn tạm dừng cho đến khi thread có quyền ưu tiên cao hơn kết thúc việc sử dụng tài nguyên. Bất kỳ khi nào, có hai thread có quyền ưu tiên bằng nhau cần cùng tài nguyên cùng một thời điểm, thread nào truy cập tài nguyên đầu tiên giành được quyền sử dụng tài nguyên. Những gì xảy ra cho thread thứ hai phụ thuộc vào hệ điều hành mà bạn đang chạy chương trình. Một số hệ điều hành bắt thread thứ hai chờ cho đến khi thread thứ nhất kết thúc sử dụng tài nguyên. Hệ điều hành khác yêu cầu thread đầu tiên để thread thứ hai truy cập tài nguyên sau một khoảng thời gian xác định. Điều này để chắc chắn rằng một thread không chiếm dụng tài nguyên và ngăn các thread khác sử dụng nó.
Trong thế giới thực, thread đầu tiên thường tạm dừng trong khi sử dụng tài nguyên bởi vì tài nguyên khác nó cần không có sẵn. Trong suốt thời gian tạm dừng đó, hệ điều hành để thread đầu tiên giải phóng tài nguyên. Vấn đề là bạn không biết khi nào thời gian tạm dừng xảy ra. Do đó tốt nhất là luôn luôn để một thread tạm dừng sau một khoảng thời gian bất cứ khi nào thread đang sử dụng tài nguyên suốt một khoảng thời gian dài. Theo cách này, thread chia sẻ tài nguyên với những thread khác.
Bạn cần nhớ rằng có một mặt tiêu cực khi tạm dừng một thread trong một khoảng thời gian một cách tự động. Việc dừng một thread làm giảm đi khả năng thực thi của chương trình của bạn và có thể gây ra một lỗi backlog trong việc sử dụng tài nguyên. Do đó bạn cần quan sát việc thực thi chương trình của bạn một cách đều đặn để chắc chắn rằng bạn không phải chịu đựng sự ảnh hưởng tiêu cực của việc dừng một thread.
Bây giờ, hãy tập trung vào những gì bạn làm để điều khiển – ấn định quyền ưu tiên của một thread. Bạn ấn định quyền ưu tiên của một thread bằng cách gọi method setPriority(), được định nghĩa trong class Thread. Method setPriority() yêu cầu một tham số, đó là một số nguyên thay thế cho mức độ của quyền ưu tiên. Bạn có hai cách để thay thế quyền ưu tiên. Bạn có thể sử dụng một số nguyên từ 1 đến 10, hoặc bạn có thể sử dụng các biến final được định nghĩa trong class Thread. Các biến này là MAX_PRIORITY, MIN_PRIORITY và NORM_PRIORITY.
Bạn có thể xác định được mức độ ưu tiên của thread bằng method getPriority(), cũng được định nghĩa trong class Thread. Method getPriority() không yêu cầu tham số nào, và nó trả về một số nguyên thay thế cho mức độ của quyền ưu tiên của thread.
Ví dụ dưới đây chỉ ra làm thế nào để sử dụng method setPriority() và method getPriority(). Ví dụ này tạo ra hai child thread và ấn định quyền ưu tiên cho mỗi thread. Đầu tiên thread có quyền ưu tiên thấp bắt đầu, và sau đó là thread có quyền ưu tiên cao. Dưới đây là những gì hiển thị khi chạy chương trình (chú ý rằng thread có quyền ưu tiên cao chạy trước thread có quyền ưu tiên thấp mặc dù thread có quyền ưu tiên thấp bắt đầu trước
low priority started
high priority started
high priority running.
low priority running.
low priority stopped.
high priority stopped.
Mã nguồn:
PHP Code:
class MyThread implements Runnable {
Thread t;
private volatile boolean running = true;
public MyThread (int p, String tName) {
t = new Thread(this,tName);
t.setPriority (p);
}
public void run() {
System.out.println(t.getName() + " running.");
}
public void stop() {
running = false;
System.out.println(t.getName() + " stopped.");
}
public void start() {
System.out.println(t.getName() + " started");
t.start();
}
}
class Demo {
public static void main(String args[] ) {
Thread.currentThread().setPriority(10);
MyThread lowPriority = new MyThread (3, "low priority");
MyThread highPriority = new MyThread (7, "high priority");
lowPriority.start();
highPriority.start();
try {
Thread .sleep(1000);
} catch ( InterruptedException e) {
System.out.println("Main thread interrupted.");
}
lowPriority.stop();
highPriority.stop();
try {
highPriority.t.join();
lowPriority.t.join();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
Việc đồng bộ hóa một method là cách tốt nhất để hạn chế việc sử dụng một method tại một thời điểm. Tuy nhiên sẽ có những trường hợp mà bạn không thể đồng bộ hóa một method, chẳng hạn như khi bạn sử dụng một class được cung cấp bởi bên thứ ba. Trong những trường hợp như thế, bạn không được phép truy cập vào định nghĩa lớp, sẽ ngăn bạn sử dụng từ khóa synchronized.
Sử dụng phát biểu được đồng bộ hoá
Một cách khác để sử dụng từ khóa synchronized là sử dụng phát biểu được đồng bộ hóa. Một phát biểu được đồng bộ hóa chứa một block được đồng bộ hóa , mà bên trong đó đặt những đối tượng và những method được đồng bộ hóa. Gọi các method chứa block được đồng bộ hóa xảy ra khi một thread có được monitor của đối tượng.
Mặc dù bạn có thể gọi những method bên trong một block được đồng bộ hóa, việc công bố method phải được thực hiện bên ngoài một block được đồng bộ hóa.
Ví dụ dưới đây chỉ cách làm thế nào để sử dụng một phát biểu được đồng bộ hóa. Ví dụ này cơ bản cũng giống ví dụ trước, tuy nhiên phát biểu được đồng bộ hóa được sử dụng thay vì từ khóa synchronized. Phát biểu này được đặt trong method run() của class MyThread. Phát biểu được đồng bộ hóa sẽ đồng bộ hóa instance của class Parentheses và vì thế ngăn hai thread sử dụng method display() cùng một lúc.
class Parentheses {
void display(String s) {
System.out.print (”(” + s);
try {
Thread.sleep (1000);
} catch (InterruptedException e) {
System.out.println (”Interrupted”);
}
System.out.println(”)”);
}
}
class MyThread implements Runnable {
String s1;
Parentheses p1;
Thread t;
public MyThread (Parentheses p2, String s2) {
p1= p2;
s1= s2;
t = new Thread(this);
t.start();
}
public void run() {
synchronized(p1){
p1.display(s1);
}
}
}
class Demo{
public static void main (String args[]) {
Parentheses p3 = new Parentheses();
MyThread name1 = new MyThread(p3, “Bob”);
MyThread name2 = new MyThread(p3, “Mary”);
try {
name1.t.join();
name2.t.join();
} catch (InterruptedException e ) {
System.out.println( “Interrupted”);
}
}
}
Ở đây, method display() không sử dụng từ khóa synchronized. Thay vào đó, phát biểu được đồng bộ hóa được sử dụng bên trong method run(). Điều này cho kết quả giống với ví dụ trước bởi vì một thread chờ một khoảng thời gian để thread còn lại kết thúc trước khi tiếp tục xử lý.
Trong phần trước, bạn đã học được mỗi thread có một quyền ưu tiên được gán được sử dụng những thread quan trọng hơn sử dụng tài nguyên. Quyền ưu tiên được sử dụng như một hướng dẫn cho hệ điều hành xác định được thread nào được truy cập đến một tài nguyên chẳng hạn như CPU. Trong thực tế, hệ điều hành đặt các trình quản lý vào trong sự quản lý của nó. Thông thường các lập trình viên có một ít hoặc không có quyền điều khiển đối với những trình quản lý khác. Vì thế, chúng thành lập quyền ưu tiên cho các thread của chúng mà không quan tâm xa hơn đến những trình quản lý khác.
Một quyền ưu tiên là một số nguyên chính xác từ 1 đến 10, trong đó 10 là quyền ưu tiên cao nhất được xem như quyền ưu tiên tối đa, và 1 là quyền ưu tiên thấp nhất được xem như quyền ưu tiên tối thiểu. Quyền ưu tiên thông thường là 5, là quyền ưu tiên mặc định cho mỗi thread.
Nói chung, một thread có quyền ưu tiên cao hơn giành việc sử dụng tài nguyên của thread có quyền ưu tiên thấp hơn. Thread có quyền ưu tiên thấp hơn tạm dừng cho đến khi thread có quyền ưu tiên cao hơn kết thúc việc sử dụng tài nguyên. Bất kỳ khi nào, có hai thread có quyền ưu tiên bằng nhau cần cùng tài nguyên cùng một thời điểm, thread nào truy cập tài nguyên đầu tiên giành được quyền sử dụng tài nguyên. Những gì xảy ra cho thread thứ hai phụ thuộc vào hệ điều hành mà bạn đang chạy chương trình. Một số hệ điều hành bắt thread thứ hai chờ cho đến khi thread thứ nhất kết thúc sử dụng tài nguyên. Hệ điều hành khác yêu cầu thread đầu tiên để thread thứ hai truy cập tài nguyên sau một khoảng thời gian xác định. Điều này để chắc chắn rằng một thread không chiếm dụng tài nguyên và ngăn các thread khác sử dụng nó.
Trong thế giới thực, thread đầu tiên thường tạm dừng trong khi sử dụng tài nguyên bởi vì tài nguyên khác nó cần không có sẵn. Trong suốt thời gian tạm dừng đó, hệ điều hành để thread đầu tiên giải phóng tài nguyên. Vấn đề là bạn không biết khi nào thời gian tạm dừng xảy ra. Do đó tốt nhất là luôn luôn để một thread tạm dừng sau một khoảng thời gian bất cứ khi nào thread đang sử dụng tài nguyên suốt một khoảng thời gian dài. Theo cách này, thread chia sẻ tài nguyên với những thread khác.
Bạn cần nhớ rằng có một mặt tiêu cực khi tạm dừng một thread trong một khoảng thời gian một cách tự động. Việc dừng một thread làm giảm đi khả năng thực thi của chương trình của bạn và có thể gây ra một lỗi backlog trong việc sử dụng tài nguyên. Do đó bạn cần quan sát việc thực thi chương trình của bạn một cách đều đặn để chắc chắn rằng bạn không phải chịu đựng sự ảnh hưởng tiêu cực của việc dừng một thread.
Bây giờ, hãy tập trung vào những gì bạn làm để điều khiển – ấn định quyền ưu tiên của một thread. Bạn ấn định quyền ưu tiên của một thread bằng cách gọi method setPriority(), được định nghĩa trong class Thread. Method setPriority() yêu cầu một tham số, đó là một số nguyên thay thế cho mức độ của quyền ưu tiên. Bạn có hai cách để thay thế quyền ưu tiên. Bạn có thể sử dụng một số nguyên từ 1 đến 10, hoặc bạn có thể sử dụng các biến final được định nghĩa trong class Thread. Các biến này là MAX_PRIORITY, MIN_PRIORITY và NORM_PRIORITY.
Bạn có thể xác định được mức độ ưu tiên của thread bằng method getPriority(), cũng được định nghĩa trong class Thread. Method getPriority() không yêu cầu tham số nào, và nó trả về một số nguyên thay thế cho mức độ của quyền ưu tiên của thread.
Ví dụ dưới đây chỉ ra làm thế nào để sử dụng method setPriority() và method getPriority(). Ví dụ này tạo ra hai child thread và ấn định quyền ưu tiên cho mỗi thread. Đầu tiên thread có quyền ưu tiên thấp bắt đầu, và sau đó là thread có quyền ưu tiên cao. Dưới đây là những gì hiển thị khi chạy chương trình (chú ý rằng thread có quyền ưu tiên cao chạy trước thread có quyền ưu tiên thấp mặc dù thread có quyền ưu tiên thấp bắt đầu trước
low priority started
high priority started
high priority running.
low priority running.
low priority stopped.
high priority stopped.
Mã nguồn:
PHP Code:
class MyThread implements Runnable {
Thread t;
private volatile boolean running = true;
public MyThread (int p, String tName) {
t = new Thread(this,tName);
t.setPriority (p);
}
public void run() {
System.out.println(t.getName() + " running.");
}
public void stop() {
running = false;
System.out.println(t.getName() + " stopped.");
}
public void start() {
System.out.println(t.getName() + " started");
t.start();
}
}
class Demo {
public static void main(String args[] ) {
Thread.currentThread().setPriority(10);
MyThread lowPriority = new MyThread (3, "low priority");
MyThread highPriority = new MyThread (7, "high priority");
lowPriority.start();
highPriority.start();
try {
Thread .sleep(1000);
} catch ( InterruptedException e) {
System.out.println("Main thread interrupted.");
}
lowPriority.stop();
highPriority.stop();
try {
highPriority.t.join();
lowPriority.t.join();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
Việc đồng bộ hóa một method là cách tốt nhất để hạn chế việc sử dụng một method tại một thời điểm. Tuy nhiên sẽ có những trường hợp mà bạn không thể đồng bộ hóa một method, chẳng hạn như khi bạn sử dụng một class được cung cấp bởi bên thứ ba. Trong những trường hợp như thế, bạn không được phép truy cập vào định nghĩa lớp, sẽ ngăn bạn sử dụng từ khóa synchronized.
Sử dụng phát biểu được đồng bộ hoá
Một cách khác để sử dụng từ khóa synchronized là sử dụng phát biểu được đồng bộ hóa. Một phát biểu được đồng bộ hóa chứa một block được đồng bộ hóa , mà bên trong đó đặt những đối tượng và những method được đồng bộ hóa. Gọi các method chứa block được đồng bộ hóa xảy ra khi một thread có được monitor của đối tượng.
Mặc dù bạn có thể gọi những method bên trong một block được đồng bộ hóa, việc công bố method phải được thực hiện bên ngoài một block được đồng bộ hóa.
Ví dụ dưới đây chỉ cách làm thế nào để sử dụng một phát biểu được đồng bộ hóa. Ví dụ này cơ bản cũng giống ví dụ trước, tuy nhiên phát biểu được đồng bộ hóa được sử dụng thay vì từ khóa synchronized. Phát biểu này được đặt trong method run() của class MyThread. Phát biểu được đồng bộ hóa sẽ đồng bộ hóa instance của class Parentheses và vì thế ngăn hai thread sử dụng method display() cùng một lúc.
class Parentheses {
void display(String s) {
System.out.print (”(” + s);
try {
Thread.sleep (1000);
} catch (InterruptedException e) {
System.out.println (”Interrupted”);
}
System.out.println(”)”);
}
}
class MyThread implements Runnable {
String s1;
Parentheses p1;
Thread t;
public MyThread (Parentheses p2, String s2) {
p1= p2;
s1= s2;
t = new Thread(this);
t.start();
}
public void run() {
synchronized(p1){
p1.display(s1);
}
}
}
class Demo{
public static void main (String args[]) {
Parentheses p3 = new Parentheses();
MyThread name1 = new MyThread(p3, “Bob”);
MyThread name2 = new MyThread(p3, “Mary”);
try {
name1.t.join();
name2.t.join();
} catch (InterruptedException e ) {
System.out.println( “Interrupted”);
}
}
}
Ở đây, method display() không sử dụng từ khóa synchronized. Thay vào đó, phát biểu được đồng bộ hóa được sử dụng bên trong method run(). Điều này cho kết quả giống với ví dụ trước bởi vì một thread chờ một khoảng thời gian để thread còn lại kết thúc trước khi tiếp tục xử lý.
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Multithreading trong Java (tiếp theo)
Giao tiếp giữa các thread
Các thread mở ra cho các lập trình viên một khoảng không mới trong lập trình, nơi mà ở đó những phần của một chương trình thực thi không đồng bộ với nhau, mỗi một xử lý độc lập với những xử lý khác. Tuy nhiên mỗi thread thỉnh thoảng cần tính toán việc xử lý của chúng và vì thế cần có thể giao tiếp với những thread khác trong suốt quá trình xử lý. Các lập trình viên gọi đây là inter-process communication (giao tiếp trong xử lý).
Bạn có thể có các thread giao tiếp với các thread khác trong chương trình của bạn bằng cách sử dụng những method wait(), notify() và notifyAll(). Những method này được gọi từ bên trong một method được đồng bộ hóa. Method wait() nói cho một thread giải phóng monitor và đi vào trạng thái suspend. Có hai dạng method wait() khác nhau. Một dạng không yêu cầu đối số và vì thế một thread sẽ chờ cho đến khi nó được thông báo. Một dạng khác có đối số để bạn xác định khoảng thời gian chờ. Bạn xác định độ dài thời gian trong mili giây và đặt nó vào trong method wait().
Method notify() nói cho một thread đang suspend bởi method wait() và lấy lại điều khiển của monitor. Method notifyAll() đánh thức tất cả các thread đang chờ điều khiển của monitor. Những thread khác chờ trong trạng thái suspend cho đến khi monitor có sẵn trở lại.
Ví dụ dưới đây chỉ cho bạn làm thế nào để sử dụng những method này trong một ứng dụng. Mục đích của chương trình là có một class Pulishser cho một giá trị cho class Consumer thông qua sử dụng class Queue. Ví dụ này định nghĩa bốn class, class Pulisher, class Comsumer, class Queue và class Demo. Class Queue định nghĩa hai instance: exchangevalue và một biến cờ. exchangevalue đặt vào một giá trị trong queue bởi publisher. Biến cờ được sử dụng như một cách đánh dấu giá trị được đặt vào trong queue. Class Queue cũng định nghĩa một method get() và một method put(). Method put() sử dụng để đặt một giá trị vào queue (gán một giá trị cho exchangevalue), method get() sử dụng để nhận giá trị chứa trong queue (trả về giá trị của exchangevalue. Khi một giá trị được gán, method put() thay đổi giá trị của biến cờ từ false thành true xác định một giá trị được đặt vào trong queue. Chú ý giá trị của biến cờ được sử dụng như thế nào trong method get() và method put() để có thread gọi method chờ cho đến khi có một giá trị trong queue hoặc không có giá trị nào trong queue, phụ thuộc vào method nào đang được gọi.
Class Publisher công bố một instance của class Queue và sau đó gọi method put() đặt vào năm số nguyên integer trong queue. Mặc dù method put() được đặt trong một vòng lặp for, mỗi số nguyên integer được đặt vào trong queue, và sau đó có một khoảng tạm dừng cho đến khi số nguyên integer được nhận bởi class Consumer.
Class Consumer tương tự như thiết kế class Publisher, ngoại trừ class Consumer gọi method get() năm lần bên trong một vòng lặp for. Mỗi lần gọi, method get() tạm dừng cho đến khi class Publisher đặt một số nguyên integer vào trong queue.
Method main() của class Demo tạo ra các instance của class Publisher, class Consumer và class Queue. Chú ý rằng các khởi dựng của của class Publisher và class Consumer đều đặt vào một reference đến instance của class Queue. Chúng sử dụng instance của class Queue cho inter-process communication.
Dưới đây là những gì mà bạn sẽ thấy khi chạy chương trình và mã nguồn của ví dụ
Put: 0
Get: 0
Put: 1
Get: 1
Put: 2
Get: 2
Put: 3
Get: 3
Put: 4
Get: 4
class Queue {
int exchangevalue;
boolean busy = false;
synchronized int get() {
if (!busy)
try {
wait();
} catch (InterruptedException e) {
System.out.println(
“Get: InterruptedException”);
}
System.out.println(”Get: ” + exchangevalue);
notify();
return exchangevalue;
}
synchronized void put (int exchangevalue) {
if (busy)
try {
wait();
} catch (InterruptedException e) {
System.out.println(
“Put: InterruptedException”);
}
this.exchangevalue = exchangevalue;
busy = true;
System.out.println(”Put: ” + exchangevalue);
notify();
}
}
class Publisher implements Runnable {
Queue q;
Publisher(Queue q) {
this.q = q;
new Thread (this, “Publisher”).start();
}
public void run() {
for (int i = 0; i < 5; i++){
q.put(i);
}
}
}
class Consumer implements Runnable {
Queue q;
Consumer (Queue q) {
this.q = q;
new Thread (this, “Consumer”).start();
}
public void run() {
for (int i = 0; i < 5; i++){
q.get();
}
}
}
class Demo {
public static void main(String args []) {
Queue q = new Queue ();
new Publisher (q);
new Consumer (q);
}
}
Suspending và Resuming Thread
Ví dụ này định nghĩa một class MyThread. Class MyThread định nghĩa ba method: method run(), method suspendThread(), và method resumeThread(). Thêm vào đó, class MyThread công bố biến instance suspended, mà giá trị được sử dụng để chỉ ra thread có suspend hay không.
Method run() chứa một vòng lặp for để hiển thị giá trị của biến counter. Mỗi lần biến counter được hiển thị, thread dừng một khoảng thời gian.Sau đó là một phát biểu synchronized để xác định giá trị của biến instance suspended là true hay không. Nếu có, method wait() được gọi, làm cho thread đi vào trạng thái suspend cho đến khi method notify() được gọi.
Method suspendThread() đơn giản chỉ gán giá trị true cho biến instance suspended. Method resumeThread() gán false cho biến instance suspended và sau đó gọi method notify(). Điều này sẽ làm cho thread đang ở trạng thái suspend phục hồi xử lý.
Method main() của class Demo công bố một instance của MyThread và sau đó tạm dừng khoảng 1 giây trước khi gọi method suspendThread() và hiển thị thông điệp tương ứng trên màn hình. Sau đó nó lại tạm dừng một khoảng thời gian trước khi gọi method resumeThread() và hiển thị thông điệp tương ứng trên màn hình một lần nữa.
Thread tiếp tục hiển thị giá trị của biến đếm counter cho đến khi thread đã đi vào trạng thái suspend. Thread tiếp tục hiển thị giá trị của biến counter một khi thread phục hồi xử lý. Đây là những gì hiển thị khi bạn chạy chương trình này và mã nguồn
Thread: 0
Thread: 1
Thread: 2
Thread: 3
Thread: 4
Thread: Suspended
Thread: Resume
Thread: 5
Thread: 6
Thread: 7
Thread: 8
Thread: 9
Thread exiting.
PHP Code:
class MyThread implements Runnable {
String name;
Thread t;
boolean suspended;
MyThread() {
t = new Thread(this, "Thread");
suspended = false ;
t.start();
}
public void run() {
try {
for (int i = 0; i < 10; i++) {
System.out.println("Thread: " + i );
Thread.sleep(200);
synchronized (this) {
while (suspended) {
wait();
}
}
}
} catch (InterruptedException e ) {
System.out.println("Thread: interrupted.");
}
System.out.println("Thread exiting.");
}
void suspendThread() {
suspended = true;
}
synchronized void resumeThread() {
suspended = false;
notify();
}
}
class Demo {
public static void main (String args [] ) {
MyThread t1 = new MyThread();
try{
Thread.sleep(1000);
t1.suspendThread();
System.out.println("Thread: Suspended");
Thread.sleep(1000);
t1.resumeThread();
System.out.println("Thread: Resume");
} catch ( InterruptedException e) {
}
try {
t1.t.join();
} catch ( InterruptedException e) {
System.out.println ("Main Thread: interrupted");
}
}
}
Các thread mở ra cho các lập trình viên một khoảng không mới trong lập trình, nơi mà ở đó những phần của một chương trình thực thi không đồng bộ với nhau, mỗi một xử lý độc lập với những xử lý khác. Tuy nhiên mỗi thread thỉnh thoảng cần tính toán việc xử lý của chúng và vì thế cần có thể giao tiếp với những thread khác trong suốt quá trình xử lý. Các lập trình viên gọi đây là inter-process communication (giao tiếp trong xử lý).
Bạn có thể có các thread giao tiếp với các thread khác trong chương trình của bạn bằng cách sử dụng những method wait(), notify() và notifyAll(). Những method này được gọi từ bên trong một method được đồng bộ hóa. Method wait() nói cho một thread giải phóng monitor và đi vào trạng thái suspend. Có hai dạng method wait() khác nhau. Một dạng không yêu cầu đối số và vì thế một thread sẽ chờ cho đến khi nó được thông báo. Một dạng khác có đối số để bạn xác định khoảng thời gian chờ. Bạn xác định độ dài thời gian trong mili giây và đặt nó vào trong method wait().
Method notify() nói cho một thread đang suspend bởi method wait() và lấy lại điều khiển của monitor. Method notifyAll() đánh thức tất cả các thread đang chờ điều khiển của monitor. Những thread khác chờ trong trạng thái suspend cho đến khi monitor có sẵn trở lại.
Ví dụ dưới đây chỉ cho bạn làm thế nào để sử dụng những method này trong một ứng dụng. Mục đích của chương trình là có một class Pulishser cho một giá trị cho class Consumer thông qua sử dụng class Queue. Ví dụ này định nghĩa bốn class, class Pulisher, class Comsumer, class Queue và class Demo. Class Queue định nghĩa hai instance: exchangevalue và một biến cờ. exchangevalue đặt vào một giá trị trong queue bởi publisher. Biến cờ được sử dụng như một cách đánh dấu giá trị được đặt vào trong queue. Class Queue cũng định nghĩa một method get() và một method put(). Method put() sử dụng để đặt một giá trị vào queue (gán một giá trị cho exchangevalue), method get() sử dụng để nhận giá trị chứa trong queue (trả về giá trị của exchangevalue. Khi một giá trị được gán, method put() thay đổi giá trị của biến cờ từ false thành true xác định một giá trị được đặt vào trong queue. Chú ý giá trị của biến cờ được sử dụng như thế nào trong method get() và method put() để có thread gọi method chờ cho đến khi có một giá trị trong queue hoặc không có giá trị nào trong queue, phụ thuộc vào method nào đang được gọi.
Class Publisher công bố một instance của class Queue và sau đó gọi method put() đặt vào năm số nguyên integer trong queue. Mặc dù method put() được đặt trong một vòng lặp for, mỗi số nguyên integer được đặt vào trong queue, và sau đó có một khoảng tạm dừng cho đến khi số nguyên integer được nhận bởi class Consumer.
Class Consumer tương tự như thiết kế class Publisher, ngoại trừ class Consumer gọi method get() năm lần bên trong một vòng lặp for. Mỗi lần gọi, method get() tạm dừng cho đến khi class Publisher đặt một số nguyên integer vào trong queue.
Method main() của class Demo tạo ra các instance của class Publisher, class Consumer và class Queue. Chú ý rằng các khởi dựng của của class Publisher và class Consumer đều đặt vào một reference đến instance của class Queue. Chúng sử dụng instance của class Queue cho inter-process communication.
Dưới đây là những gì mà bạn sẽ thấy khi chạy chương trình và mã nguồn của ví dụ
Put: 0
Get: 0
Put: 1
Get: 1
Put: 2
Get: 2
Put: 3
Get: 3
Put: 4
Get: 4
class Queue {
int exchangevalue;
boolean busy = false;
synchronized int get() {
if (!busy)
try {
wait();
} catch (InterruptedException e) {
System.out.println(
“Get: InterruptedException”);
}
System.out.println(”Get: ” + exchangevalue);
notify();
return exchangevalue;
}
synchronized void put (int exchangevalue) {
if (busy)
try {
wait();
} catch (InterruptedException e) {
System.out.println(
“Put: InterruptedException”);
}
this.exchangevalue = exchangevalue;
busy = true;
System.out.println(”Put: ” + exchangevalue);
notify();
}
}
class Publisher implements Runnable {
Queue q;
Publisher(Queue q) {
this.q = q;
new Thread (this, “Publisher”).start();
}
public void run() {
for (int i = 0; i < 5; i++){
q.put(i);
}
}
}
class Consumer implements Runnable {
Queue q;
Consumer (Queue q) {
this.q = q;
new Thread (this, “Consumer”).start();
}
public void run() {
for (int i = 0; i < 5; i++){
q.get();
}
}
}
class Demo {
public static void main(String args []) {
Queue q = new Queue ();
new Publisher (q);
new Consumer (q);
}
}
Suspending và Resuming Thread
Ví dụ này định nghĩa một class MyThread. Class MyThread định nghĩa ba method: method run(), method suspendThread(), và method resumeThread(). Thêm vào đó, class MyThread công bố biến instance suspended, mà giá trị được sử dụng để chỉ ra thread có suspend hay không.
Method run() chứa một vòng lặp for để hiển thị giá trị của biến counter. Mỗi lần biến counter được hiển thị, thread dừng một khoảng thời gian.Sau đó là một phát biểu synchronized để xác định giá trị của biến instance suspended là true hay không. Nếu có, method wait() được gọi, làm cho thread đi vào trạng thái suspend cho đến khi method notify() được gọi.
Method suspendThread() đơn giản chỉ gán giá trị true cho biến instance suspended. Method resumeThread() gán false cho biến instance suspended và sau đó gọi method notify(). Điều này sẽ làm cho thread đang ở trạng thái suspend phục hồi xử lý.
Method main() của class Demo công bố một instance của MyThread và sau đó tạm dừng khoảng 1 giây trước khi gọi method suspendThread() và hiển thị thông điệp tương ứng trên màn hình. Sau đó nó lại tạm dừng một khoảng thời gian trước khi gọi method resumeThread() và hiển thị thông điệp tương ứng trên màn hình một lần nữa.
Thread tiếp tục hiển thị giá trị của biến đếm counter cho đến khi thread đã đi vào trạng thái suspend. Thread tiếp tục hiển thị giá trị của biến counter một khi thread phục hồi xử lý. Đây là những gì hiển thị khi bạn chạy chương trình này và mã nguồn
Thread: 0
Thread: 1
Thread: 2
Thread: 3
Thread: 4
Thread: Suspended
Thread: Resume
Thread: 5
Thread: 6
Thread: 7
Thread: 8
Thread: 9
Thread exiting.
PHP Code:
class MyThread implements Runnable {
String name;
Thread t;
boolean suspended;
MyThread() {
t = new Thread(this, "Thread");
suspended = false ;
t.start();
}
public void run() {
try {
for (int i = 0; i < 10; i++) {
System.out.println("Thread: " + i );
Thread.sleep(200);
synchronized (this) {
while (suspended) {
wait();
}
}
}
} catch (InterruptedException e ) {
System.out.println("Thread: interrupted.");
}
System.out.println("Thread exiting.");
}
void suspendThread() {
suspended = true;
}
synchronized void resumeThread() {
suspended = false;
notify();
}
}
class Demo {
public static void main (String args [] ) {
MyThread t1 = new MyThread();
try{
Thread.sleep(1000);
t1.suspendThread();
System.out.println("Thread: Suspended");
Thread.sleep(1000);
t1.resumeThread();
System.out.println("Thread: Resume");
} catch ( InterruptedException e) {
}
try {
t1.t.join();
} catch ( InterruptedException e) {
System.out.println ("Main Thread: interrupted");
}
}
}
NguyenHoangThien(I22B)- Tổng số bài gửi : 38
Join date : 15/03/2013
Sự khác nhau giữa lập trình đa luồng và đa tiến trình
Giống nhau :
- Luồng còn được gọi là tiến trình nhẹ
- Đều có thông tin trạng thái
- Nhiều luồng hoặc nhiều tiến trình có thể liên quan đến một chương trình
- Chia sẻ tài nguyên cho nhau
- Tăng tốc tính toán
- Đảm bảo tính đơn thể
Khác nhau:
- Do luồng cùng vận hành trong 1 vùng địa chỉ vì vậy dễ dùng chung tài nguyên hơn đa tiến trình
VD : Mượn đồ dùng trong gia đình thì dễ hơn mượn của hàng xóm
- Do luồng chung tài nguyên với cha và các luồng khác nên việc tạo lập, chuyển ngữ cảnh cũng
nhanh hơn tiến trình
VD : Việc ngăn riêng ra một phòng trong nhà thì nhanh hơn là mua một căn hộ nữa
- Cấp phát bộ nhớ và tài nguyên cho tiến trình thì tốn kém hơn luồng
- Lập trình đa luồng thì dễ hơn lập trình đa tiến trình
- Luồng còn được gọi là tiến trình nhẹ
- Đều có thông tin trạng thái
- Nhiều luồng hoặc nhiều tiến trình có thể liên quan đến một chương trình
- Chia sẻ tài nguyên cho nhau
- Tăng tốc tính toán
- Đảm bảo tính đơn thể
Khác nhau:
- Do luồng cùng vận hành trong 1 vùng địa chỉ vì vậy dễ dùng chung tài nguyên hơn đa tiến trình
VD : Mượn đồ dùng trong gia đình thì dễ hơn mượn của hàng xóm
- Do luồng chung tài nguyên với cha và các luồng khác nên việc tạo lập, chuyển ngữ cảnh cũng
nhanh hơn tiến trình
VD : Việc ngăn riêng ra một phòng trong nhà thì nhanh hơn là mua một căn hộ nữa
- Cấp phát bộ nhớ và tài nguyên cho tiến trình thì tốn kém hơn luồng
- Lập trình đa luồng thì dễ hơn lập trình đa tiến trình
NguyenTienDat (I22A)- Tổng số bài gửi : 19
Join date : 10/03/2013
Age : 33
Trả lời với trích dẫn nội dung bài viết này SỰ LIÊN LẠC GIỮA CÁC TIẾN TRÌNH(INTERPROCESS COMUNICATION)
1. Nhu cầu liên lạc giữa các tiến trình
Trong môi trường đa chương, một tiến trình không đơn độc trong hệ thống , mà có thể ảnh hưởng đến các tiến trình khác , hoặc bị các tiến trình khác tác động. Nói cách khác, các tiến trình là những thực thể độc lập , nhưng chúng vẫn có nhu cầu liên lạc với nhau để :
- Chia sẻ thông tin: nhiều tiến trình có thể cùng quan tâm đến những dữ liệu nào đó, do vậy hệ điều hành cần cung cấp một môi trường cho phép sự truy cập đồng thời đến các dữ liệu chung.
- Hợp tác hoàn thành tác vụ: đôi khi để đạt được một sự xử lý nhanh chóng, người ta phân chia một tác vụ thành các công việc nhỏ có thể tiến hành song song. Thường thì các công việc nhỏ này cần hợp tác với nhau để cùng hoàn thành tác vụ ban đầu, ví dụ dữ liệu kết xuất của tiến trình này lại là dữ liệu nhập cho tiến trình khác .Trong các trường hợp đó, hệ điều hành cần cung cấp cơ chế để các tiến trình có thể trao đổi thông tin với nhau.
2. Các vấn đề nảy sinh trong việc liên lạc giữa các tiến trình
Do mỗi tiến trình sỡ hữu một không gian địa chỉ riêng biệt, nên các tiến trình không thể liên lạc trực tiếp dễ dàng mà phải nhờ vào các cơ chế do hệ điều hành cung cấp. Khi cung cấp cơ chế liên lạc cho các tiến trình, hệ điều hành thường phải tìm giải pháp cho các vấn đề chính yếu sau :
Liên kết tường minh hay tiềm ẩn (explicit naming/implicit naming) : tiến trình có cần phải biết tiến trình nào đang trao đổi hay chia sẻ thông tin với nó ? Mối liên kết được gọi là tường minh khi được thiết lập rõ ràng , trực tiếp giữa các tiến trình, và là tiềm ẩn khi các tiến trình liên lạc với nhau thông qua một qui ước ngầm nào đó.
Liên lạc theo chế độ đồng bộ hay không đồng bộ (blocking / non-blocking): khi một tiến trình trao đổi thông tin với một tiến trình khác, các tiến trình có cần phải đợi cho thao tác liên lạc hoàn tất rồi mới tiếp tục các xử lý khác ? Các tiến trình liên lạc theo cơ chế đồng bộ sẽ chờ nhau hoàn tất việc liên lạc, còn các tiến trình liên lạc theo cơ chế nonblocking thì không.
Liên lạc giữa các tiến trình trong hệ thống tập trung và hệ thống phân tán: cơ chế liên lạc giữa các tiến trình trong cùng một máy tính có sự khác biệt với việc liên lạc giữa các tiến trình giữa những máy tính khác nhau?
Trong môi trường đa chương, một tiến trình không đơn độc trong hệ thống , mà có thể ảnh hưởng đến các tiến trình khác , hoặc bị các tiến trình khác tác động. Nói cách khác, các tiến trình là những thực thể độc lập , nhưng chúng vẫn có nhu cầu liên lạc với nhau để :
- Chia sẻ thông tin: nhiều tiến trình có thể cùng quan tâm đến những dữ liệu nào đó, do vậy hệ điều hành cần cung cấp một môi trường cho phép sự truy cập đồng thời đến các dữ liệu chung.
- Hợp tác hoàn thành tác vụ: đôi khi để đạt được một sự xử lý nhanh chóng, người ta phân chia một tác vụ thành các công việc nhỏ có thể tiến hành song song. Thường thì các công việc nhỏ này cần hợp tác với nhau để cùng hoàn thành tác vụ ban đầu, ví dụ dữ liệu kết xuất của tiến trình này lại là dữ liệu nhập cho tiến trình khác .Trong các trường hợp đó, hệ điều hành cần cung cấp cơ chế để các tiến trình có thể trao đổi thông tin với nhau.
2. Các vấn đề nảy sinh trong việc liên lạc giữa các tiến trình
Do mỗi tiến trình sỡ hữu một không gian địa chỉ riêng biệt, nên các tiến trình không thể liên lạc trực tiếp dễ dàng mà phải nhờ vào các cơ chế do hệ điều hành cung cấp. Khi cung cấp cơ chế liên lạc cho các tiến trình, hệ điều hành thường phải tìm giải pháp cho các vấn đề chính yếu sau :
Liên kết tường minh hay tiềm ẩn (explicit naming/implicit naming) : tiến trình có cần phải biết tiến trình nào đang trao đổi hay chia sẻ thông tin với nó ? Mối liên kết được gọi là tường minh khi được thiết lập rõ ràng , trực tiếp giữa các tiến trình, và là tiềm ẩn khi các tiến trình liên lạc với nhau thông qua một qui ước ngầm nào đó.
Liên lạc theo chế độ đồng bộ hay không đồng bộ (blocking / non-blocking): khi một tiến trình trao đổi thông tin với một tiến trình khác, các tiến trình có cần phải đợi cho thao tác liên lạc hoàn tất rồi mới tiếp tục các xử lý khác ? Các tiến trình liên lạc theo cơ chế đồng bộ sẽ chờ nhau hoàn tất việc liên lạc, còn các tiến trình liên lạc theo cơ chế nonblocking thì không.
Liên lạc giữa các tiến trình trong hệ thống tập trung và hệ thống phân tán: cơ chế liên lạc giữa các tiến trình trong cùng một máy tính có sự khác biệt với việc liên lạc giữa các tiến trình giữa những máy tính khác nhau?
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
TRÌNH BÀY NGUYÊB LÝ TẬP LUỒNG VÀ CHO VÍ DỤ MINH HỌA
TẬP LUỒNG:
- Tiến trình cha tạo lập sẵn một tập luồng khi khởi động
- Các luồng trong tập luồng luôn sẵn sàng chờ công việc
-Khi tiến trình cha nhận thêm một yêu cầu một luồng được đánh thức và đưa vào vận hành
-Phục vụ xong luồng được trả về tập luồng
-Nếu số yêu cầu lớn hơn số luồng trong tập tiến trình cha chờ đến khi có luồng được giải phóng
ví dụ: trong doanh trại quân đội sẽ có một tướng lĩnh ( tiến trình cha) và sẽ có một đội binh( tập luồng)
đội binh này sẽ sẵn sàng chiến đấu khi có mệnh lệnh( sẵn sàng chờ công việc)
khi có một tên địch đột nhập tướng lĩnh sẽ điều binh sỹ một đi bắt tên địch
trong khi đó lại có thêm 1 tên địch khác đột nhập tưỡng lĩnh sẽ điều binh sỹ 2 đi bắt địch .sau khi bắt địch xong binh sĩ sẽ trở về doanh trại
- Tiến trình cha tạo lập sẵn một tập luồng khi khởi động
- Các luồng trong tập luồng luôn sẵn sàng chờ công việc
-Khi tiến trình cha nhận thêm một yêu cầu một luồng được đánh thức và đưa vào vận hành
-Phục vụ xong luồng được trả về tập luồng
-Nếu số yêu cầu lớn hơn số luồng trong tập tiến trình cha chờ đến khi có luồng được giải phóng
ví dụ: trong doanh trại quân đội sẽ có một tướng lĩnh ( tiến trình cha) và sẽ có một đội binh( tập luồng)
đội binh này sẽ sẵn sàng chiến đấu khi có mệnh lệnh( sẵn sàng chờ công việc)
khi có một tên địch đột nhập tướng lĩnh sẽ điều binh sỹ một đi bắt tên địch
trong khi đó lại có thêm 1 tên địch khác đột nhập tưỡng lĩnh sẽ điều binh sỹ 2 đi bắt địch .sau khi bắt địch xong binh sĩ sẽ trở về doanh trại
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
Những lợi ích của lập trình đa luồng
1.Sự đáp ứng: đa luồng một ứng dụng giao tiếp cho phép một chương trình tiếp tục chạy thậm chí nếu một phần của nó bị khóa hay đang thực hiện một thao tác dài, do đó gia tăng sự đáp ứng đối với người dùng. Thí dụ, một trình duyệt web vẫn có thể đáp ứng người dùng bằng một luồng trong khi một ảnh đang được nạp bằng một luồng khác.
2.Chia sẻ tài nguyên: Mặc định, các luồng chia sẻ bộ nhớ và các tài nguyên của các quá trình mà chúng thuộc về. Thuận lợi của việc chia sẽ mã là nó cho phép một ứng dụng có nhiều hoạt động của các luồng khác nhau nằm trong cùng không gian địa chỉ.
3.Kinh tế: cấp phát bộ nhớ và các tài nguyên cho việc tạo các quá trình là rất
đắt. Vì các luồng chia sẻ tài nguyên của quá trình mà chúng thuộc về nên nó kinh tế hơn để tạo và chuyển ngữ cảnh giữa các luồng. Khó để đánh giá theo kinh nghiệm sự khác biệt chi phí cho việc tạo và duy trì một quá trình hơn một luồng, nhưng thường nó sẽ mất nhiều thời gian để tạo và quản lý một quá trình hơn một luồng. Trong Solaris 2, tạo một quá trình chậm hơn khoảng 30 lần tạo một luồng và chuyển đổi ngữ cảnh chậm hơn 5 lần.
4.Sử dụng kiến trúc đa xử lý: các lợi điểm của đa luồng có thể phát huy trong
kiến trúc đa xử lý, ở đó mỗi luồng thực thi song song trên một bộ xử lý khác nhau. Một quá trình đơn luồng chỉ có thể chạy trên một CPU. Đa luồng trên một máy nhiều CPU gia tăng tính đồng hành. Trong kiến trúc đơn xử lý, CPU thường chuyển đổi qua lại giữa mỗi luồng quá nhanh để tạo ra hình ảnh của sự song song nhưng trong thực tế chỉ một luồng đang chạy tại một thời điểm..
2.Chia sẻ tài nguyên: Mặc định, các luồng chia sẻ bộ nhớ và các tài nguyên của các quá trình mà chúng thuộc về. Thuận lợi của việc chia sẽ mã là nó cho phép một ứng dụng có nhiều hoạt động của các luồng khác nhau nằm trong cùng không gian địa chỉ.
3.Kinh tế: cấp phát bộ nhớ và các tài nguyên cho việc tạo các quá trình là rất
đắt. Vì các luồng chia sẻ tài nguyên của quá trình mà chúng thuộc về nên nó kinh tế hơn để tạo và chuyển ngữ cảnh giữa các luồng. Khó để đánh giá theo kinh nghiệm sự khác biệt chi phí cho việc tạo và duy trì một quá trình hơn một luồng, nhưng thường nó sẽ mất nhiều thời gian để tạo và quản lý một quá trình hơn một luồng. Trong Solaris 2, tạo một quá trình chậm hơn khoảng 30 lần tạo một luồng và chuyển đổi ngữ cảnh chậm hơn 5 lần.
4.Sử dụng kiến trúc đa xử lý: các lợi điểm của đa luồng có thể phát huy trong
kiến trúc đa xử lý, ở đó mỗi luồng thực thi song song trên một bộ xử lý khác nhau. Một quá trình đơn luồng chỉ có thể chạy trên một CPU. Đa luồng trên một máy nhiều CPU gia tăng tính đồng hành. Trong kiến trúc đơn xử lý, CPU thường chuyển đổi qua lại giữa mỗi luồng quá nhanh để tạo ra hình ảnh của sự song song nhưng trong thực tế chỉ một luồng đang chạy tại một thời điểm..
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
So sánh luồng và tiến trình
Giống nhau:
+Luồng thực ra cũng là một tiến trình hay nó còn được gọi là tiến trình nhẹ
+Luồng là một bộ phân của tiến trình hệ thống
+Nhiều luồng hoặc nhiều tiến trình thì sẽ ảnh hưởng tới toàn chương trình
+Luồng và tiến trình đều có thông tin trạng thái
Khác nhau:
+Tạo mới luồng nhanh hơn tạo mới tiến trình
Ví dụ: Việc ngăn một phong mới trong nhà để ở thì sẽ dễ dàng hơn nhiều so với việc xây một ngôi nhà mới.
+Việc chuyển ngữ cảnh của tiến trình này sang tiến trình khác chậm hơn 5 lần việc chuyển ngữ cảnh từ luồng sang luồng
+Lập trình đa luồng thì dễ hơn lâp trình đa tiến trình
+Cấp phát bộ nhớ cho luồng thì nhanh hơn cho tiến trình.
+Luồng thực ra cũng là một tiến trình hay nó còn được gọi là tiến trình nhẹ
+Luồng là một bộ phân của tiến trình hệ thống
+Nhiều luồng hoặc nhiều tiến trình thì sẽ ảnh hưởng tới toàn chương trình
+Luồng và tiến trình đều có thông tin trạng thái
Khác nhau:
+Tạo mới luồng nhanh hơn tạo mới tiến trình
Ví dụ: Việc ngăn một phong mới trong nhà để ở thì sẽ dễ dàng hơn nhiều so với việc xây một ngôi nhà mới.
+Việc chuyển ngữ cảnh của tiến trình này sang tiến trình khác chậm hơn 5 lần việc chuyển ngữ cảnh từ luồng sang luồng
+Lập trình đa luồng thì dễ hơn lâp trình đa tiến trình
+Cấp phát bộ nhớ cho luồng thì nhanh hơn cho tiến trình.
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
Những ưu việt của công nghệ đa luồng
+ Đảm bảo được khả năng đáp ứng của tiến trình tốt hơn.
Khi lập trình đa luồng thì một khi 1 luồng có sự cố thì luồng khác vẫn làm việc, vẫn phản hồi ,trong trường hợp lập trình đơn luồng khi gặp sự cố thì luồng đó sẽ chậm và làm chậm luôn cả tiến trình, đa luồng một ứng dụng giao tiếp cho phép một chương trình tiếp tục chạy thậm chí nếu một phần của nó bị khóa hay đang thực hiện một thao tác dài, do đó gai tăng sự đáp ứng đối với người dùng.
Ví dụ : Các cô ở tổng đài 108 là các luồng , khi khách hàng điện thoại hỏi 108, thì một trong các cô (người thứ nhất) sẽ trả lời, nếu trong thời điểm đó khách hàng thứ hai gọi 108,thì một trong các cô (cô thứ 2) còn lại sẽ trả lời
+ Theo mặc định các luồng có thể dùng chung bộ nhớ và tai nguyên của luồng cha.
Thuận lợi của việc chia sẻ mã là nó cho phép một ứng dụng có nhiều hoạt động của các luồng khác nằm trong cùng không gian, địa chỉ,vài luồng cùng vận hành trong một vùng địa chỉ dễ dùng chung tài nguyên hơn so với trường hợp đa tiến trình.
Ví dụ :Trong lớp chúng ta có thể dùng bảng củ lớp mình, chúng ta có thể chia sẻ các thông tin cần thiết cho tất cả các thành viên ở trong lớp biết,trong khi chúng ta khong thể dùng chung bảng của lớp khác để chia sẻ thông tin cho lớp mình được.
+ Tiết kiệm (Economy) :
Cấp phát bộ nhớ và tài nguyên cho tiến trình là công việc rất tốn kém. Do luồng có thể dùng chung tài nguyên với luồng cha và các luồng khác, việc tạo lập ngữ cảnh cũng nhanh hơn (Solaris2, tạo tiến trình chậm hơn 30 lần, chuyển ngữ cảnh chậm hơn 5 lần
Ví dụ : Các bạn trong lớp là các luồng đang dùng chung một cái bảng của lớp, ai cần ghi thì ghi, ai cần thì chụp hình về xem
Có thể bố trí một chỗ ngồi ở trong lớp cho một bạn đến sau dễ dàng hơn việc làm một chiếc ghế khác cho bạn đó.
+ Chuyển ngữ cảnh từ luồng này sang luồng khác thì nhanh hơn chuyển ngữ cảnh từ tiến trình này sang tiến trình khác.
+ Tận dụng được ưu thế kiến trúc đa xử lý (nhiều CPU). Khi đa luồng thì 1 luồng dùng CPU này và 1 luồng dùng CPU khác sẽ nhanh hơn và các luồng có thể làm việc song song , mỗi luồng có thể chạy bởi CPU riêng. Tiến trình đa luồng sẽ làm việc nhanh hơn tiến trình đơn luồng.
+ Lập trình đa luồng dễ dàng hơn lập trình đa tiến trình
Khi lập trình đa luồng thì một khi 1 luồng có sự cố thì luồng khác vẫn làm việc, vẫn phản hồi ,trong trường hợp lập trình đơn luồng khi gặp sự cố thì luồng đó sẽ chậm và làm chậm luôn cả tiến trình, đa luồng một ứng dụng giao tiếp cho phép một chương trình tiếp tục chạy thậm chí nếu một phần của nó bị khóa hay đang thực hiện một thao tác dài, do đó gai tăng sự đáp ứng đối với người dùng.
Ví dụ : Các cô ở tổng đài 108 là các luồng , khi khách hàng điện thoại hỏi 108, thì một trong các cô (người thứ nhất) sẽ trả lời, nếu trong thời điểm đó khách hàng thứ hai gọi 108,thì một trong các cô (cô thứ 2) còn lại sẽ trả lời
+ Theo mặc định các luồng có thể dùng chung bộ nhớ và tai nguyên của luồng cha.
Thuận lợi của việc chia sẻ mã là nó cho phép một ứng dụng có nhiều hoạt động của các luồng khác nằm trong cùng không gian, địa chỉ,vài luồng cùng vận hành trong một vùng địa chỉ dễ dùng chung tài nguyên hơn so với trường hợp đa tiến trình.
Ví dụ :Trong lớp chúng ta có thể dùng bảng củ lớp mình, chúng ta có thể chia sẻ các thông tin cần thiết cho tất cả các thành viên ở trong lớp biết,trong khi chúng ta khong thể dùng chung bảng của lớp khác để chia sẻ thông tin cho lớp mình được.
+ Tiết kiệm (Economy) :
Cấp phát bộ nhớ và tài nguyên cho tiến trình là công việc rất tốn kém. Do luồng có thể dùng chung tài nguyên với luồng cha và các luồng khác, việc tạo lập ngữ cảnh cũng nhanh hơn (Solaris2, tạo tiến trình chậm hơn 30 lần, chuyển ngữ cảnh chậm hơn 5 lần
Ví dụ : Các bạn trong lớp là các luồng đang dùng chung một cái bảng của lớp, ai cần ghi thì ghi, ai cần thì chụp hình về xem
Có thể bố trí một chỗ ngồi ở trong lớp cho một bạn đến sau dễ dàng hơn việc làm một chiếc ghế khác cho bạn đó.
+ Chuyển ngữ cảnh từ luồng này sang luồng khác thì nhanh hơn chuyển ngữ cảnh từ tiến trình này sang tiến trình khác.
+ Tận dụng được ưu thế kiến trúc đa xử lý (nhiều CPU). Khi đa luồng thì 1 luồng dùng CPU này và 1 luồng dùng CPU khác sẽ nhanh hơn và các luồng có thể làm việc song song , mỗi luồng có thể chạy bởi CPU riêng. Tiến trình đa luồng sẽ làm việc nhanh hơn tiến trình đơn luồng.
+ Lập trình đa luồng dễ dàng hơn lập trình đa tiến trình
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
Các trạng thái của luồng ( Thread States )
1-Running : đang chạy – được hiểu là khi hệ thống định rõ vị trí luồng trong CPU
2-Ready to run : đã chạy ( nhưng chưa được định vị trí trong CPU )
3-Resumed : luồng ở trạng thái “ready to run” sau khi suspended/ blocked
4-Suspended : luồng tự nguyện dừng lại để cho 1 luồng khác chạy
5-Blocked : luồng đang đợi tài nguyên để tiếp tục hoặc bị 1 sự kiện của hệ thống
chặn ngang
2-Ready to run : đã chạy ( nhưng chưa được định vị trí trong CPU )
3-Resumed : luồng ở trạng thái “ready to run” sau khi suspended/ blocked
4-Suspended : luồng tự nguyện dừng lại để cho 1 luồng khác chạy
5-Blocked : luồng đang đợi tài nguyên để tiếp tục hoặc bị 1 sự kiện của hệ thống
chặn ngang
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
Một số hàm thông dụng của Thread
start bắt đầu thực thi thread
• sleep đưa trạng thái về trạng thái đợi (không thực thi nữa)
• resume thực thi lại thread từ trạng thái đợi hoặc dead-lock
• join đợi để cho đến khi thread này chết
• isAlive kiểm tra thread còn đang sống hay đã bị kill
• getName lấy tên của thread
• getPriority trả về độ ưu tiên của thread
• setName đặt tên cho thread
• setPriority đặt độ ưu tiên cho thread
• …
Ví dụ tương tự việc sử dụng thread với Runnable interface, chúng ta cũng có thể kế thừa tự lớp có sẵn là Thread như sau:
class StringThread extends Thread {
public void run() {
System.out.println("Inherit successfully from Thread class!");
}
}
public class TestClass {
public static void main(String[] args) {
StringThread t = new StringThread();
new Thread(t).start();
}
}
Kết quả in ra sẽ là: Inherit successfully from Thread class!
1.3 Các lớp Timer, TimerTask và SchedulingTask
Timer là một lớp tiện ích giúp cho việc lập lịch và kiểm soát việc thực thi một task vụ nào đó. Ví dụ bạn muốn dùng việc cập nhật thông trong 5 phút tới, hay thông tin chỉ được tồn tại 10h sau đó sẽ tự động bị xóa đi,… Một số hàm thông dụng trong Timer như:
• schedule lên lịch để thực thi task khi nào bắt đầu, kết thúc hay lặp lại, …
• cancel dừng timer và hủy tất cả các task đã lên lịch trong timer
• purge xóa tất cả các task đã dùng trong hàng đợi timer
TimerTask là một lớp trừu tượng implement Runnable interface, nó giúp cho việc lập lịch thực thi các thread
Ví dụ ta có một lớp MyTimerTask kế thừa từ TimerTask như bên dưới
class MyTimerTask extends TimerTask {
public void run() {
System.out.println("Running the scheduled task by Timer");
System.gc();
}
}
public class TestClass {
public static void main(String[] args) {
Timer timer = new Timer();
MyTimerTask task = new MyTimerTask();
timer.schedule(task, 3000, 2000);//Execute task after 3 senconds and then repeat in 2 seconds period
}
}
Kết quả in ra màn hình sau 5 giây sẽ là: Running the scheduled task by Timer
Running the scheduled task by Timer
• sleep đưa trạng thái về trạng thái đợi (không thực thi nữa)
• resume thực thi lại thread từ trạng thái đợi hoặc dead-lock
• join đợi để cho đến khi thread này chết
• isAlive kiểm tra thread còn đang sống hay đã bị kill
• getName lấy tên của thread
• getPriority trả về độ ưu tiên của thread
• setName đặt tên cho thread
• setPriority đặt độ ưu tiên cho thread
• …
Ví dụ tương tự việc sử dụng thread với Runnable interface, chúng ta cũng có thể kế thừa tự lớp có sẵn là Thread như sau:
class StringThread extends Thread {
public void run() {
System.out.println("Inherit successfully from Thread class!");
}
}
public class TestClass {
public static void main(String[] args) {
StringThread t = new StringThread();
new Thread(t).start();
}
}
Kết quả in ra sẽ là: Inherit successfully from Thread class!
1.3 Các lớp Timer, TimerTask và SchedulingTask
Timer là một lớp tiện ích giúp cho việc lập lịch và kiểm soát việc thực thi một task vụ nào đó. Ví dụ bạn muốn dùng việc cập nhật thông trong 5 phút tới, hay thông tin chỉ được tồn tại 10h sau đó sẽ tự động bị xóa đi,… Một số hàm thông dụng trong Timer như:
• schedule lên lịch để thực thi task khi nào bắt đầu, kết thúc hay lặp lại, …
• cancel dừng timer và hủy tất cả các task đã lên lịch trong timer
• purge xóa tất cả các task đã dùng trong hàng đợi timer
TimerTask là một lớp trừu tượng implement Runnable interface, nó giúp cho việc lập lịch thực thi các thread
Ví dụ ta có một lớp MyTimerTask kế thừa từ TimerTask như bên dưới
class MyTimerTask extends TimerTask {
public void run() {
System.out.println("Running the scheduled task by Timer");
System.gc();
}
}
public class TestClass {
public static void main(String[] args) {
Timer timer = new Timer();
MyTimerTask task = new MyTimerTask();
timer.schedule(task, 3000, 2000);//Execute task after 3 senconds and then repeat in 2 seconds period
}
}
Kết quả in ra màn hình sau 5 giây sẽ là: Running the scheduled task by Timer
Running the scheduled task by Timer
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
Ưu điểm và nhược điểm của một ứng dụng Multithreaded (đa luồng)
1- Lợi thế của một ứng dụng Multithreaded
* Cải thiện hiệu suất và đồng thời
Đối với các ứng dụng nhất định, hiệu quả và đồng thời có thể được cải thiện bằng cách sử dụng đa luồng và multicontexting với nhau. Trong các ứng dụng khác, hiệu suất có thể không bị ảnh hưởng hoặc thậm chí bị suy thoái bằng cách sử dụng đa luồng và multicontexting với nhau. Làm thế nào hiệu suất bị ảnh hưởng phụ thuộc vào ứng dụng của bạn.
* Đơn giản hóa mã hóa các cuộc gọi thủ tục từ xa và các cuộc hội thoại
Trong một số ứng dụng nó được dễ dàng hơn để mã cuộc gọi thủ tục khác nhau từ xa và các cuộc hội thoại trong chủ đề riêng biệt hơn để quản lý chúng từ cùng một thread.
* Đồng thời tiếp cận với nhiều ứng dụng
BEA Tuxedo khách hàng của bạn có thể được kết nối với nhiều ứng dụng cùng một lúc.
* Giảm số lượng máy chủ cần thiết
Bởi vì một máy chủ có thể gửi chủ đề dịch vụ nhiều, số lượng máy chủ để bắt đầu cho ứng dụng của bạn bị giảm. Khả năng này cho nhiều đề cử đặc biệt hữu ích cho các máy chủ thoại, nếu không phải được dành riêng cho một khách hàng cho toàn bộ thời gian của cuộc hội thoại.
Đối với các ứng dụng, trong đó chủ đề của khách hàng được tạo ra bởi Microsoft Internet Information Server API hoặc giao diện Netscape Enterprise Server (có nghĩa là, các NSAPI), việc sử dụng nhiều đề tài là điều cần thiết nếu bạn muốn có được những lợi ích đầy đủ khả năng bởi những công cụ này.
2- Nhược điểm của một ứng dụng Multithreaded
• Khó khăn của việc viết mã
ứng dụng Multithreaded và multicontexted không dễ dàng để viết. Chỉ lập trình viên có kinh nghiệm nên thực hiện mã hóa cho các loại ứng dụng.
• Khó khăn của gỡ rối
Đó là khó khăn hơn nhiều để tái tạo một lỗi trong ứng dụng đa luồng hoặc multicontexted hơn là để làm như vậy trong một ứng dụng đơn luồng đơn contexted,. Kết quả là, nó là khó khăn hơn, trong trường hợp trước đây, để xác định và xác minh nguyên nhân gốc rễ khi lỗi xảy ra.
• Khó khăn của việc quản lý đồng thời
Các nhiệm vụ quản lý tương tranh giữa các chủ đề rất khó khăn và có tiềm năng để giới thiệu những vấn đề mới vào ứng dụng.
• Khó khăn thử nghiệm
Kiểm tra một ứng dụng đa luồng là khó khăn hơn thử nghiệm một ứng dụng đơn luồng, vì khuyết tật này thường liên quan đến thời gian và khó khăn hơn để sinh sản.
• Khó khăn của porting mã hiện tại
Code hiện tại thường đòi hỏi quan trọng tái kiến trúc để tận dụng đa luồng. Các lập trình viên cần phải:
o Hủy bỏ các biến tĩnh
o Thay thế bất kỳ chức năng cuộc gọi mà không phải là thread-safe
o Thay thế các mã khác mà không phải là thread-safe
Bởi vì các cảng đã hoàn thành phải được kiểm tra và tái kiểm tra, công việc yêu cầu một cổng đa luồng ứng dụng là đáng kể.
* Cải thiện hiệu suất và đồng thời
Đối với các ứng dụng nhất định, hiệu quả và đồng thời có thể được cải thiện bằng cách sử dụng đa luồng và multicontexting với nhau. Trong các ứng dụng khác, hiệu suất có thể không bị ảnh hưởng hoặc thậm chí bị suy thoái bằng cách sử dụng đa luồng và multicontexting với nhau. Làm thế nào hiệu suất bị ảnh hưởng phụ thuộc vào ứng dụng của bạn.
* Đơn giản hóa mã hóa các cuộc gọi thủ tục từ xa và các cuộc hội thoại
Trong một số ứng dụng nó được dễ dàng hơn để mã cuộc gọi thủ tục khác nhau từ xa và các cuộc hội thoại trong chủ đề riêng biệt hơn để quản lý chúng từ cùng một thread.
* Đồng thời tiếp cận với nhiều ứng dụng
BEA Tuxedo khách hàng của bạn có thể được kết nối với nhiều ứng dụng cùng một lúc.
* Giảm số lượng máy chủ cần thiết
Bởi vì một máy chủ có thể gửi chủ đề dịch vụ nhiều, số lượng máy chủ để bắt đầu cho ứng dụng của bạn bị giảm. Khả năng này cho nhiều đề cử đặc biệt hữu ích cho các máy chủ thoại, nếu không phải được dành riêng cho một khách hàng cho toàn bộ thời gian của cuộc hội thoại.
Đối với các ứng dụng, trong đó chủ đề của khách hàng được tạo ra bởi Microsoft Internet Information Server API hoặc giao diện Netscape Enterprise Server (có nghĩa là, các NSAPI), việc sử dụng nhiều đề tài là điều cần thiết nếu bạn muốn có được những lợi ích đầy đủ khả năng bởi những công cụ này.
2- Nhược điểm của một ứng dụng Multithreaded
• Khó khăn của việc viết mã
ứng dụng Multithreaded và multicontexted không dễ dàng để viết. Chỉ lập trình viên có kinh nghiệm nên thực hiện mã hóa cho các loại ứng dụng.
• Khó khăn của gỡ rối
Đó là khó khăn hơn nhiều để tái tạo một lỗi trong ứng dụng đa luồng hoặc multicontexted hơn là để làm như vậy trong một ứng dụng đơn luồng đơn contexted,. Kết quả là, nó là khó khăn hơn, trong trường hợp trước đây, để xác định và xác minh nguyên nhân gốc rễ khi lỗi xảy ra.
• Khó khăn của việc quản lý đồng thời
Các nhiệm vụ quản lý tương tranh giữa các chủ đề rất khó khăn và có tiềm năng để giới thiệu những vấn đề mới vào ứng dụng.
• Khó khăn thử nghiệm
Kiểm tra một ứng dụng đa luồng là khó khăn hơn thử nghiệm một ứng dụng đơn luồng, vì khuyết tật này thường liên quan đến thời gian và khó khăn hơn để sinh sản.
• Khó khăn của porting mã hiện tại
Code hiện tại thường đòi hỏi quan trọng tái kiến trúc để tận dụng đa luồng. Các lập trình viên cần phải:
o Hủy bỏ các biến tĩnh
o Thay thế bất kỳ chức năng cuộc gọi mà không phải là thread-safe
o Thay thế các mã khác mà không phải là thread-safe
Bởi vì các cảng đã hoàn thành phải được kiểm tra và tái kiểm tra, công việc yêu cầu một cổng đa luồng ứng dụng là đáng kể.
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
một so ví dụ về đa luồng trong Java
đa luồng trong Java theo mình nghĩ là Thread.
Mục tiêu của Thread là để tạo ra nhiều tiểu trình chạy song song với nhau để thực hiện 1 số việc nào đó. Để làm vậy, cần tạo 1 lớp như sau:
1. Implement interface Runnable
2. Extends lớp Thread và overide hàm run().
ví dụ:
class Apple extends Thread {
void run() {}
}
public class test{
public void main(){
Apple a = new Apple();
a.start();
}
}
Lưu ý là: hàm run() chỉ là để chạy tiểu trình sẽ thực hiện song song, còn để gọi nó thì phải xài hàm start(). Còn ko gọi, mà gọi run() trực tiếp thì nó sẽ ko chạy song song mà nó sẽ chạy như 1 hàm bình thường, tức là chỉ có 1 tiểu trình chạy mà thôi chứ ko phải 2.
Ngoài ra, bạn cũng có thể tìm hiểu về hàm join(), sleep(), wait(), notify(), yeild() và có thể là setPriority()...
Cụ thể hơn một tí nè các bạn
join(): nếu a gọi b.join() thì khi b thực hiện xong công việc thì a mới chạy tiếp.
wait(): nếu a gọi b.wait() thì a sẽ tạm dừng và đợi cho b khi nào làm xong cái trò gì đó, gọi notify() hay notifyAll() thì a mới chạy tiếp.
notify(): cái này dùng để báo mấy thread khác đang đợi được phép chạy tiếp. Lưu ý là wait() với notify() phải ở trong một khối synchronize mới chịu chạy.
sleep(): nếu a chạy sleep() thì nó sẽ dừng lại bao nhiêu giây rồi chạy tiếp.
yeild(): nếu a gọi lệnh này, nó từ trạng thái đang chạy sẽ bị quánh bật về trạng thái sẵn sàng, dùng lệnh này để cho mấy thread khác có cơ hội chạy. Nhưng nó chỉ có tác dụng với các thread có cùng độ ưu tiên.
setPriority(): chỉ định độ ưu tiên cho một thread. thread có độ ưu tiên cao hơn sẽ được chạy và chiếm cpu nhiều hơn.
Mục tiêu của Thread là để tạo ra nhiều tiểu trình chạy song song với nhau để thực hiện 1 số việc nào đó. Để làm vậy, cần tạo 1 lớp như sau:
1. Implement interface Runnable
2. Extends lớp Thread và overide hàm run().
ví dụ:
class Apple extends Thread {
void run() {}
}
public class test{
public void main(){
Apple a = new Apple();
a.start();
}
}
Lưu ý là: hàm run() chỉ là để chạy tiểu trình sẽ thực hiện song song, còn để gọi nó thì phải xài hàm start(). Còn ko gọi, mà gọi run() trực tiếp thì nó sẽ ko chạy song song mà nó sẽ chạy như 1 hàm bình thường, tức là chỉ có 1 tiểu trình chạy mà thôi chứ ko phải 2.
Ngoài ra, bạn cũng có thể tìm hiểu về hàm join(), sleep(), wait(), notify(), yeild() và có thể là setPriority()...
Cụ thể hơn một tí nè các bạn
join(): nếu a gọi b.join() thì khi b thực hiện xong công việc thì a mới chạy tiếp.
wait(): nếu a gọi b.wait() thì a sẽ tạm dừng và đợi cho b khi nào làm xong cái trò gì đó, gọi notify() hay notifyAll() thì a mới chạy tiếp.
notify(): cái này dùng để báo mấy thread khác đang đợi được phép chạy tiếp. Lưu ý là wait() với notify() phải ở trong một khối synchronize mới chịu chạy.
sleep(): nếu a chạy sleep() thì nó sẽ dừng lại bao nhiêu giây rồi chạy tiếp.
yeild(): nếu a gọi lệnh này, nó từ trạng thái đang chạy sẽ bị quánh bật về trạng thái sẵn sàng, dùng lệnh này để cho mấy thread khác có cơ hội chạy. Nhưng nó chỉ có tác dụng với các thread có cùng độ ưu tiên.
setPriority(): chỉ định độ ưu tiên cho một thread. thread có độ ưu tiên cao hơn sẽ được chạy và chiếm cpu nhiều hơn.
dangthihoangly(I12A)- Tổng số bài gửi : 64
Join date : 10/03/2012
Age : 34
Đến từ : Quang ngai
Re: Thảo luận Bài 5
Với công nghệ CGI thì khi có 5 client cùng gửi yêu cầu một lúc (cập nhật thông tin để ứng tuyển) thì khi đó mỗi yêu cầu sẽ tạo 1 file .exe trên server (mỗi yêu cầu là một tiến trình mà tiến trình thì rất nặng) sẽ dẫn đến server bị đứng (Lúc Thầy vào thì chính xác là có 5 cửa sổ trên thanh task bar).NguyenHoangThien(I22B) đã viết:Năm 1999. internet ở Việt Nam chưa phổ biến, nhà nước và các công ty lớn sử dụng mạng vitranet của microsoft. Các client sẽ quay số đến server để truy xuất 1 trang web. Database = SQL server, hệ điều hành: NT 4.0. Công ty mạng Phương Nam phát triển 1 trang web giới thiệu việc làm qua mạng. Client quay số đến và giới thiệu bản thân, mức lương yêu cầu để đăng lên web. Nhược điểm của ứng dụng này là: khi có 5 client cùng quay số đến địa chỉ giới thiệu việc làm thì server bị treo. Công ty mời thầy đến để kiểm tra và lãnh đạo công ty cho rằng bị hư phần cứng. Không cần kiểm tra phần cứng, thầy đã chỉ ra ngay vấn đề của ứng dụng là do công ty sử dụng công nghệ CGI (common gateway interface) là công nghệ lập trình đa tiến trình. Với công nghệ này, khi có 1 client quay số đến thì CGI sẽ phát sinh 1 tiến trình nặng để thực hiện. 5 tiến trình nặng chạy 1 lúc trên server sẽ làm server bị treo. Giải pháp: thầy viết lại ứng dụng bằng công nghệ ASP (active server pages) là công nghệ đa luồng. Khi sử dụng công nghệ này thì mỗi client khi quay số đến sẽ được phục vụ bằng 1 luồng (nhẹ hơn tiến trình) nên server sẽ không bị treo.
Admin
Không phải vậy !
NguyenHoangKimVu (I11C)- Tổng số bài gửi : 62
Join date : 25/08/2011
Lý do có hàm Sleep(1);
- Code:
Sleep(1);// ngủ 1 ms,(chờ in tăng lên 1) rồi mới showbuffer !
ShowBuffer();
Một bạn trong lớp chụp hình cả lớp và đứng chờ bấm máy. Nếu bạn đó chụp ngay không chờ các bạn khác chuẩn bị thì bức ảnh sẽ bị lỡ, xấu đi (Ngưởi sẽ nhìn hướng này, hướng kia, làm việc riêng không tập trung nhìn vào máy). Người chụp hình khi đó sẽ rơi vào trạng thái ngủ một tí - chờ mọi người chuẩn bị xong hoàn toàn thì bức ảnh chụp nó mới hoàn hảo, đẹp.
NguyenHoangKimVu (I11C)- Tổng số bài gửi : 62
Join date : 25/08/2011
Re: Thảo luận Bài 5
NguyenHoangKimVu (I11C) đã viết:Ví dụ :
- Code:
Sleep(1);// ngủ 1 ms,(chờ in tăng lên 1) rồi mới showbuffer !
ShowBuffer();
Một bạn trong lớp chụp hình cả lớp và đứng chờ bấm máy. Nếu bạn đó chụp ngay không chờ các bạn khác chuẩn bị thì bức ảnh sẽ bị lỡ, xấu đi (Ngưởi sẽ nhìn hướng này, hướng kia, làm việc riêng không tập trung nhìn vào máy). Người chụp hình khi đó sẽ rơi vào trạng thái ngủ một tí - chờ mọi người chuẩn bị xong hoàn toàn thì bức ảnh chụp nó mới hoàn hảo, đẹp.
Giúp đồng bộ hóa công việc của luồng chính. Dừng lại một chút nó sẽ đánh thức 1 nhà SX nào đấy =>int tăng lên 1.
vd: Một lớp học đang học, Thầy đang giảng các bạn nghe rất chăm chú. Sau đó có một bạn đi học trễ xin Thầy vô lớp, khi đó Thầy ngừng giảng và các bạn cũng nghĩ một tí. trang thái Thầy ngưng dạy là trang thái ngủ và có một bạn vô lớp là gúp INT tăng lên 1..
NguyenHuuMinh80(I22B)- Tổng số bài gửi : 8
Join date : 13/03/2013
Age : 35
Trang 3 trong tổng số 8 trang • 1, 2, 3, 4, 5, 6, 7, 8
Similar topics
» Ôn tập thi Cuối kỳ
» Thảo luận các vấn đề của Môn học
» Thảo luận Bài 3
» Thảo luận bài 4
» Thảo luận Bài 7
» Thảo luận các vấn đề của Môn học
» Thảo luận Bài 3
» Thảo luận bài 4
» Thảo luận Bài 7
Trang 3 trong tổng số 8 trang
Permissions in this forum:
Bạn không có quyền trả lời bài viết