Được chỉnh sửa ngày 03/06/2021.
Chào mừng các bạn đã đến với bài học Java số 41, bài học về Thread. Đây là bài học trong chuỗi bài về lập trình ngôn ngữ Java của Yellow Code Books.
Thời gian qua có rất nhiều bạn hỏi mình kiến thức Java bao giờ sẽ kết thúc. Vâng, mình cũng muốn thông báo với các bạn rằng chúng ta cũng đang cận kề với các bài học cuối cùng lắm rồi. Tuy nhiên mình cũng muốn các bạn biết rằng, thực ra cái sự kết thúc này chỉ là ở chừng mực các bài học của mình mà thôi. Kiến thức Java còn rất nhiều, mình hi vọng sẽ còn được nói nhiều hơn về các khía cạnh khác của Java ở các chủ đề khác. Và trong khi các bài viết sẽ không thể theo kịp tốc độ ham học hỏi của các bạn, thì mình mong các bạn cũng nên “thủ sẵn” cho riêng bạn các kho tài liệu học tập Java giá trị khác nhé.
Quay lại bài học về Thread. Như mình có nói từ bài học số 1, ngay khi bạn vừa mới chập chững biết đến Java là gì, thì mình cũng có nói đến một trong những thế mạnh của ngôn ngữ này, đó là Hỗ trợ chạy đa nhiệm (Multithread) rất tốt. Và mãi cho đến bài học hôm nay, thì chúng ta mới cùng nhau làm rõ hơn cái sự mạnh mẽ này của Java.
Khái Niệm Thread, Hay Multithread
Thread hay Multithread đều có ý nghĩa như nhau trong kiến thức của bài học này. Thread dịch ra tiếng Việt là Luồng, và Multithread là Đa luồng. Luồng ở đây chính là Luồng xử lý của hệ thống. Và bởi vì lý do chính đáng để cho Thread ra đời cũng chính là để cho các ứng dụng có thể điều khiển nhiều Thread khác nhau một cách đồng thời, mà nhiều Thread đồng thời như vậy cũng có nghĩa là Đa Thread, hay Multithread. Chính vì vậy mà kiến thức Thread hay Multithread cũng chỉ là một.
Vai trò của Thread hay Multithread dĩ nhiên là cái gì đó liên quan đến Đa Luồng, Đa Nhiệm rồi. Nói cụ thể ra đó là hệ thống sẽ hỗ trợ chúng ta tách các tác vụ của ứng dụng ra làm nhiều Luồng (hay Thread), và hệ thống sẽ giúp xử lý các Luồng này một cách đồng thời. Như vậy nếu theo như những gì chúng ta làm quen với Java từ trước đến giờ, đó là nếu chúng ta có các tác vụ A, B, C, với các cách code cũ, hệ thống sẽ luôn xử lý tuần tự các tác vụ này, giả sử A sẽ được xử lý trước tiên, rồi đến B, và cuối cùng là đến C. Nhưng sau bài học hôm nay, nếu chúng ta tổ chức sao cho mỗi A, B và C là mỗi Thread, thì sẽ rất tuyệt vì chúng ta hoàn toàn có thể kêu hệ thống xử lý cả A, B và C cùng một lúc.
Một ví dụ thực tế để dễ hình dung hơn về Thread như sau. Giả sử bạn đang dùng ứng dụng Google Maps trên nền Android được viết bằng Java. Bạn có nhu cầu tìm một địa chỉ trên bản đồ, địa chỉ đó là “Chợ Bến Thành” chẳng hạn.
Khi bạn gõ từng chữ cái vào khung tìm kiếm ở trên cùng của màn hình, bạn mong muốn được thấy các gợi ý địa điểm sẽ liên tục được cập nhật theo từng chữ bạn gõ vào ở dưới. Như hình trên. Bạn thấy rằng, nếu không có Thread, hệ thống sẽ đợi bạn gõ xong một chữ, rồi mới bắt đầu tìm kiếm và gợi ý các địa điểm liên quan đến chữ đó, và trong lúc hệ thống đang tìm kiếm, bạn không thể gõ được chữ kế tiếp, vì với cách làm này, cùng một lúc hệ thống chỉ đáp ứng một chuyện thôi, hoặc là nhận ký tự bạn gõ hoặc là tìm kiếm, hết. Nhưng với việc áp dụng Multithread, chúng ta sẽ có 2 Thread chạy song song, một Thread nhận dữ liệu nhập vào của người dùng, Thread còn lại cứ dựa vào dữ liệu đã nhập đấy mà tìm kiếm, điều này làm cho trải nghiệm của người dùng được trọn vẹn, hệ thống mượt mà, nhanh chóng, không bị giật.
Bạn có thể xem mình minh họa việc đáp ứng của hệ thống đối với từng trường hợp tìm kiếm như ví dụ trên ở hình bên dưới. Trong đó, để tìm thấy kết quả “Chợ Bến Thành” xuất hiện trong danh sách gợi ý. Thì với cột Không Multithread bên trái, việc bạn gõ một từ rồi đợi hệ thống tìm kiếm, thì kết quả tìm được sẽ rất lâu so với cột MultiThread bên phải, việc bạn gõ và việc hệ thống tìm kiếm được tách ra, và thực hiện một cách song song nhau, là rất nhanh chóng và dễ chịu.
Phân Biệt Các Khái Niệm Liên Quan
Mục này mình nói thêm, cho các bạn mới tiếp cận với Thread (thậm chí với các bạn đã hiểu rõ Thread rồi) đỡ bị lăn tăn khi đọc các tài liệu liên quan đến kiến thức hôm nay. Khi đó hẳn các bạn sẽ bị loạn lên với các khái niệm sau: Thread, Multithread, Task, Multitask, Process, Multiprocess.
Đầu tiên, ở mức bao quát nhất, bạn đều biết các hệ thống máy tính ở thời đại ngày nay đều được nhắc đến với việc có khả năng xử lý đa nhiệm. Đa nhiệm ở đây chính là việc xử lý nhiều nhiệm vụ cùng một lúc. Việc xử lý đa nhiệm này càng ngày càng phổ biến và được quan tâm nhiều hơn khi các dòng máy tính đều cho ra đời các cỗ máy với nhiều CPU. Như vậy cái nhiệm vụ mà hệ thống cần xử lý đó thường được gọi là Task, và một hệ thống đa nhiệm được gọi là Multitask.
Từ nhu cầu muốn xử lý Multitask đó, hệ thống mới định ngĩa ra các Process. Process được hiểu là một chương trình. Khi ứng dụng của bạn được khởi chạy, chúng sẽ được hệ thống tạo ra một Process và ứng dụng đó sẽ được thực thi và được quản lý bên trong Process đó. Hệ thống sẽ quản lý một lúc nhiều Process khác nhau, mỗi Process như vậy được cấp phát các tài nguyên hệ thống một cách độc lập với nhau. Và bởi cùng một lúc có thể có nhiều Process (hay nhiều ứng dụng) chạy song song với nhau, nên người ta gọi cái sự Đa Process này là Multiprocess.
Khi một Process được tạo, ứng dụng bên trong Process đó có thể tạo ra nhiều Thread khác. Về cơ bản thì Thread cũng sẽ được hệ thống quản lý như Process vậy, tức là chúng có thể được chạy song song với nhau, nên mới có thêm khái niệm Multithread. Nhưng các Thread bên trong một Process chỉ được hoạt động bên trong giới hạn của Process đó thôi. Các Thread sẽ được sử dụng các tài nguyên y như là Process của nó được phép. Nhưng có một khác biệt đó là các Thread rất nhẹ và có thể dễ dàng chia sẻ tài nguyên dùng chung với nhau bên trong một Process.
Như vậy thôi. Và mặc dù lan man nhiều khái niệm như vậy, nhưng bạn nên nhớ, bài học này chúng ta chỉ quan tâm đến một loại khái niệm mà thôi, đó chính là Thread.
Khi Nào Thì Sử Dụng Thread
Câu hỏi này tuy dễ trả lời, song nếu suy nghĩ kỹ nó lại chứa đựng nhiều thông tin hơn chúng ta tưởng.
Đầu tiên như mình có nói đến một cách giông dài trên kia rằng, nếu như bạn muốn có nhiều tác vụ muốn làm việc đồng thời với nhau, thì hãy sử dụng các Thread. Chẳng hạn bạn vừa muốn ứng dụng lấy thông tin người dùng nhập gì vào khung hội thoại, vừa gọi lên server để kiểm tra kết quả nhập vào. Hay nếu bạn lập trình game, bạn vừa muốn game nhận tín hiệu điều khiển từ bàn phím, song song với việc vẽ nhân vật trên màn hình theo sự điều khiển đó, song song với việc điều khiển các chướng ngại vật, hoặc điều khiển các đường đạn bắn, các hiển thị về điểm số, v.v…
Ý thứ hai trong việc sử dụng Thread là, cũng na ná như việc muốn xử lý các tác vụ đồng thời, nhưng khi này bạn mong muốn được điều khiển các Luồng theo một sự đồng bộ nhất định. Chẳng hạn bạn khởi động nhiều Thread trong một ứng dụng, nhưng bạn muốn các Thread khác tuy được khởi động nhưng khoan hãy chạy, mà phải đợi một Thread nào đó kết thúc thì mới được hoạt động. Ở Tập 3 của loạt bài về Thread mình sẽ nói rõ cách sử dụng này của Thread.
Ý thứ ba trong việc sử dụng Thread, cũng không ngoài việc muốn xử lý các tác vụ đồng thời, nhưng khi này là tình huống khi bạn muốn ứng dụng thực thi các tác vụ quá lớn. Lớn ở đây thường là lớn về mặt thời gian. Ví dụ khi ứng dụng phải download một file từ server, hay phải thực hiện công việc gì đó mà thời gian hoàn thành của nó không phải tức thời. Khi đó nếu không có Thread, các tác vụ lâu lắc này có thể sẽ làm ảnh hưởng nghiêm trọng đến trải nghiệm của người dùng.
Chúng ta sẽ đến phần ví dụ về Thread thông qua bài thực hành sau đây để giúp bạn hiểu rõ hơn.
Thực Hành Xây Dựng Ứng Dụng Quay Số Ngẫu Nhiên
Bài thực hành này giúp bạn có một cảm quan ban đầu về việc Thread là gì và nó hoạt động như thế nào. Mình không mong muốn các bạn phải hiểu hết các dòng code của bài thực hành này, nhưng mình hi vọng các bạn sẽ thử code, và thực thi thành công chương trình. Nếu có bất kỳ lỗi nào phát sinh xảy ra với bạn thì cứ liên lạc với mình hoặc để lại comment ở dưới bài viết hôm nay nhé.
Bạn cứ tưởng tượng rằng bài thực hành này đang xây dựng một trò chơi. Trong trò chơi này có một bàn xoay, trên đó có đánh các con số từ 0 đến 100. Người chơi sẽ bắt đầu xoay bàn xoay, sau khi bàn xoay được xoay thì người chơi chẳng nhìn thấy các con số trên đó, cho đến khi họ dừng bàn xoay lại, thì con số nào ở ngay người chơi chính là con số được người chơi chọn lựa.
Ồ, ứng dụng của chúng ta sẽ không xây dựng theo kiểu một trò chơi hoàn chỉnh như thế đâu. Thay vào đó chúng ta sẽ tập trung vào logic của trò chơi. Chúng ta sẽ thay việc xoay bàn xoay bằng một lệnh gõ vào ký tự bất kỳ trên console. Sau khi nhận ký tự vừa gõ, thay vì có một bàn xoay xoay tít, thì chúng ta sẽ khởi chạy một Thread, Thread này sẽ lần lượt “quay” các con số, sao cho nó đếm tuần tự từ 0 đến 100 rồi lại quay lại số 0. Thread của chúng ta chạy mãi cho đến khi người chơi nhập thêm một ký tự từ console và Thread kết thúc. Con số mà Thread vừa “dừng” lại chính là số được người chơi chọn lựa.
Bạn đã hiểu yêu cầu của việc xây dựng trò chơi này rồi đúng không nào. Để bắt đầu vào xây dựng trò chơi, bạn nên tự tạo một project mới bằng Eclipse hoặc InteliJ. Bạn có thể đặt tên cho project này là ThreadLearning cũng được. Sau đó tạo mới một class MainClass có chứa phương thức main() trong đó.
Tiếp theo, bạn hãy tự tạo mới một lớp mới có tên CountTheNumberThread. Khoan hãy code gì cho lớp này cả. Lớp này chính là Thread với trách nhiệm “quay vòng” các con số như chúng ta đã bàn đến. Tổng quan thì ứng dụng của chúng ta có cấu trúc như hình sau.

Nào giờ bạn hãy code cho thân lớp CountTheNumberThread như sau.
public class CountTheNumberThread extends Thread { private int count = 0; private boolean isStop = false; @Override public void run() { while (!isStop) { count++; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if (count > 100) { count = 0; } } } public void end() { isStop = true; } public int getCount() { return count; } }
Dù cho có thể bạn chưa hiểu rõ về Thread, nhưng mình cũng muốn giải thích một chút, để đến bài học sau bạn sẽ dễ dàng tiếp cận với Thread hơn.
Đầu tiên thì lớp CountTheNumberThread muốn thành một Thread thì nó phải kế thừa từ lớp Thread (và còn có cách khác nữa để biến một lớp thành Thread mà bài sau chúng ta sẽ nói đến). Sau đó bên trong lớp này phải override phương thức run(). Chính các code bên trong phương thức run() sẽ là một Luồng, Luồng này sẽ được hệ thống thực thi song song với các Luồng đang thực thi khác nếu có trong hệ thống.
Trong CountTheNumberThread còn sử dụng phương thức Thread.sleep(100). Phương thức này làm cho các Thread đang chạy trở nên “ngủ” trong một khoảng thời gian được tính bằng mili giây rồi “thức dậy” và tiếp tục chạy với vòng lặp mới. Tại sao chúng ta lại cho Thread ngủ, vì cơ bản vòng lặp while được chạy với tốc độ rất nhanh, chúng ta muốn mỗi while sẽ chậm nhịp lạ một chút (100 mili giây) để sau này thuộc tính isStop bên trong CountTheNumberThread sẽ dễ được thay đổi hơn, giảm thiểu lỗi xảy ra như ở các đoạn comment bên dưới bài học hôm nay có nói đến. Chú ý là bạn phải try catch phương thức Thread.sleep() này với một Checked Exception có tên InteruptedException. Và mình sẽ nói rõ về phương thức Thread.Sleep() ở bài sau nhé.
Vậy thôi, ngoài các ý lớn mình nói đến như này ra thì các khai báo còn lại của CountTheNumberThread đều quá đỗi quen thuộc nên mình không trình bày nhiêu khê.
Đến lúc này thì CountTheNumberThread cũng chỉ là một lớp mà thôi. Muốn khởi chạy lớp này để trở thành một Thread thì mình mời bạn đến với các code ở phương thức main() như sau.
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // Đợi người dùng nhấn một phím để bắt đầu System.out.println("Nhấn phím bất kỳ để quay số"); scanner.nextLine(); // Khai báo & Khởi chạy CountTheNumberThread như là một Thread thông qua // phương thức start() CountTheNumberThread countingThread = new CountTheNumberThread(); countingThread.start(); // Đợi người dùng nhấn một phím để kết thúc System.out.println("Nhấn phím bất kỳ để kết thúc quay số"); scanner.nextLine(); // Ngừng Thread và xem hiện đang "quay" tới số nào countingThread.end(); System.out.println("Con số may mắn: " + countingThread.getCount()); }
Nhìn vào code trên, bạn có thể thấy chút khác biệt giữa việc sử dụng một Thread so với một lớp bình thường khác. Nếu như việc khởi tạo một lớp bình thường mà bạn biết so với một Thread là như nhau. Thì với một Thread, để khởi chạy Thread đó (tức là bạn biến nó thành một Luồng trong hệ thống), bạn phải gọi phương thức start() của nó, đây là phương thức được xây dựng sẵn ở lớp Thread. Khi start() được gọi, Thread cha sẽ khởi chạy các code bên trong phương thức run() mà bạn đã khai báo bên trong CountTheNumberThread. Và thế là việc đón nhận dữ liệu gõ vào từ bàn phím ở phương thức main() sẽ song song với vòng lặp bên trong phương thức run() này, không code nào phải chờ đợi code nào cả.
Nếu bạn thực thi chương trình, hãy nhập một ký tự vào console để bắt đầu “quay số” và nhập một lần nữa để kết thúc, bạn sẽ nhận được một số may mắn của riêng bạn như sau.
Opps! Mình quay ra số 69, còn bạn thì sao. Chúc bạn quay tay may mắn. 😉
Bài Tập
Với bài tập này mình muốn bạn hãy thử bỏ qua việc kế thừa Thread của lớp CountTheNumberThread, khi đó thì phương thức run() của lớp này cũng không còn từ khóa override nữa, như vậy bạn đã biến lớp này thành một lớp bình thường và run() cũng chỉ là một phương thức bình thường khác. Rồi sau đó ở main() bạn đừng gọi countingThread.start() nữa mà hãy gọi countingThread.run(). Tức là bạn không sử dụng Thread trong trường hợp này. Bạn hãy thực thi lại ứng dụng và so sánh xem việc áp dụng Thread với trò chơi này sẽ khác với việc không áp dụng Thread sẽ như thế nào nhé.
Chúng ta vừa mới tiếp cận kiến thức khá mới mẻ và thú vị của Java về vấn đề Đa nhiệm, cụ thể là Thread. Bài hôm nay chỉ mới là các kiến thức làm quen ban đầu, Thread còn rất nhiều kiến thức thú vị khác mà mình sẽ lần lượt trình bày ở các bài viết sắp tới nữa.
Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:
– Đánh giá 5 sao ở mỗi bài viết nếu thấy thích.
– Comment bên dưới mỗi bài viết nếu có thắc mắc.
– Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
– Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.
– Ủng hộ blog theo hướng dẫn ở thanh bên phải để blog ngày càng phát triển hơn.
Bài Kế Tiếp
Sau bài làm quen hôm nay, chúng ta sẽ đến phần chính của Thread. Đó chính là các kiến thức về các cách khởi tạo một Thread. Và vì Thread được xem như một tác vụ độc lập, nên chúng ta cũng sẽ xem việc kết nối với nhau giữa các Thread như thế nào nhé.
Các anhh cho em hỏi, lệnh start(). Chỉ gọi 1 lần thoi đúng không ạk. Em dùng while(true) thì bị lỗi
Có thể do while(true) của bạn làm Thread chạy hoài không ngừng gây ra lỗi về memory đấy. Bạn đừng để vòng lặp chạy lâu quá, nên dừng sớm sớm.
bạn cho mình hỏi 1 chút là : Co phải khi thực hiện hết câu lệnh trong hàm run thì thread sẽ kết thúc đúng không? .Tại sao mình dùng end để isStopped = false, hiển thị ra số may mắn mà thread vẫn chưa kết thúc ? Bạn có thể giải thíc giup mình được không
Cảm ơn ban !!!
ý là mình đã hiển thị được ra số rồi. Nhưng thread vẫn chưa chết
Thread cũng giống như các hàm khác mà thôi bạn, nó cũng thực thi từ đầu tới hết các dòng code sẽ tự kết thúc, chẳng qua Thread giúp thực hiện các dòng code này song song so với các dòng code ở Thread khác, giúp tối ưu xử lý của ứng dụng thôi. Nếu theo như ví dụ của mình trên kia thì isStop = true mới là kết thúc vòng while, vì while (!isStop) mà, nếu bạn set isStop = false trong vòng while của end(), Thread sẽ tiếp tục chạy đấy nhé.
mình cũng bị vậy, code cop của ad thì cũng ko khác gì, ko thấy chương trình exit nên mình thử getState thì thấy hiện trạng thái là RUNNABLE
T thử thay đổi 1 chút thì gặp 1 vấn đề rất khó hiểu đó là thử cho trong vòng lặp while ở method run 1 câu lệnh vô thưởng vô phạt như lệnh in ra console thì khi chạy code ở hàm main thì lúc này thread kết thúc, chương trình kết thúc theo nhưng nếu xoá câu lệnh kia đi thì mọi thứ đều ngược lại.
Sau khoảng chục lần crtl z, crtl y thì tự dưng 2 code kia cùng kết thúc chương trình y như nhau, nhưng lúc này nếu thay đổi hàm main đi thì lại ra 2 trường hợp như trên (thay đổi ko đáng kể) code như ad thì thread ko bị terminate, code thay đổi đi ít thì có. Kb có ai giải thích đc ko, cmt hơi dài nma chắc phải thế mới rõ đc ~~
Chà mình đã hiểu câu hỏi của các bạn. Theo như mình hiểu ban đầu thì logic ở bài thực hành của mình là đúng. Tuy nhiên vì một lý do nào đó mà Thread với vòng lặp while chạy nhanh quá khiến isStop không thể nào can thiệp vào được, khiến dù cho bạn có thay đổi thuộc tính này như thế nào đi nữa thì Thread vẫn SỐNG. Điều này chỉ xảy ra ở bài học của chúng ta thôi, thực tế, như trong lập trình game chẳng hạn, vòng lặp while sẽ làm rất nhiều tác vụ nặng, nó không quay lại một chu trình nhanh như bài học, chính vì vậy isStop sẽ dễ điều khiển hơn. Để tránh xảy ra lỗi này, mình có thêm vào vòng while câu lệnh Thread.sleep(100), giúp vòng while chạy ổn hơn và không gây ra lỗi nữa. Mình đã cập nhật lại bài viết mời các bạn xem qua nhé.
Ra bài nhanh lên bạn ơi, mấy tuần mới ra 1 bài mà đọc 5 phút là xong :((. Bài bạn giảng rất dễ hiểu ạ !
Có còn hơn không! Động viên bạn ấy chứ đừng có kiểu ra lệnh, giục giã. Lập trình ở VN rất ít người tốt bụng để chia sẻ như vậy
Haha dù sao cũng cảm ơn hai bạn đã ủng hộ mình, dù bằng cách này hay cách khác. Mình vẫn muốn viết nhiều hơn bây giờ, mỗi lúc rảnh là mình lại viết thôi. Phần 2 của bài Thread sắp xong rồi nhé.
wow. Những bài chia sẻ rất là chi tiết, dễ hiểu. Với lại câu từ rất hóm hỉnh. Cảm ơn tác giả nhiều nha.
bài viết tác giả rất hiểu sâu về vấn đề,
Ad ơi! Ad có thể giải thích giúp mình phần code của đoạn while(!isStop) được không ạ, ban đầu gán giá trị cho isStop = false, sau đó có thêm dấu “!” nghĩa là phủ định của isStop —> isStop lúc này là true .
Đúng rồi bạn. isStop là false, !isStrop là true. Logic này ý muốn vòng while(!isStop) phải chạy đến khi isStop là true thì dừng. Tuy nhìn hơi nghịch nghịch nhưng bạn xem đúng ý thực tế. Cách viết này mình thấy trong lập trình game hay dùng để điều khiển vòng lặp của game.
anh có viết bài về lập trình giao diện trong java không ạ?
Hiện tại thì không bạn ơi, mà mình nghĩ trong tương lai cũng vậy, mình tập trung vào các vấn đề liên quan đến ngôn ngữ, và mobile trước.
Sao code của e ra kết quả 101 được vậy ạ?
Chắc điều kiện lặp lại biến count của bạn là if (count >= 100) thay vì if (count > 100) rồi.
Vì trong code khi count > 100 thì mới gán lại giá trị cho count = 0. Khi đó để thỏa điều kiện thì count = 101 sẽ lớn hơn 100 và sẽ reset lại thành 0.
dùng if (count == 100) hoặc if (count >= 100) hoặc if (count > 99) sẽ giải quyết được chuyện này.
bài này không cần thread vẫn chạy được mà anh
Gà :#
Sao được bạn. Nhờ có Thread mà việc quay số và việc nhận sự kiện gõ ký tự từ bàn phím là song song nhau. Cái này điều khiển cái kia. Nếu không có Thread mình nghĩ bạn sẽ start được vòng while, nhưng làm sao để stop.
anh có học java me không cho em hỏi cái này cái với khó hiểu quá , cảm ơn anh
-multitask chỉ hệ thống đa nhiệm hay hệ thống chia sẻ thời gian. 1 process khi thực thi gồm các chu kỳ CPU và chu kì I/O xen kẽ nhau. Khi 1 process tiến vào chu kì I/O thì CPU sẽ thực hiện chu kỳ CPU của 1 process khác.
-multi process thường để nói đến hệ thống có từ 2 vi xử lý trở lên
-multi thread để chỉ khả năng làm các tác vụ song song trong cùng 1 ứng dụng.
Em phân biệt các khái niệm như vậy đúng chưa a?
Mình hỏi hơi ngoài lề chút : Mình hiểu rằng bạn lấy bài này cốt chủ yếu để làm ví dụ cho mọi người về thread còn đúng ra thì có thể dùng Random để tung ra con số may mắn được đúng ko ?
Chuẩn, đúng rồi bạn.
cảm ơn anh vì bài viết hay và bài viết của anh giúp em dễ hình dung với các ví dụ dễ hiểu