2008-10-23 15 views
117

Sự khác biệt giữa việc sử dụng một sợi chỉ mới và sử dụng một sợi từ hồ bơi chủ đề là gì? Lợi ích hiệu suất là gì và tại sao tôi nên xem xét sử dụng một chuỗi từ hồ bơi chứ không phải là một chủ đề mà tôi đã tạo một cách rõ ràng? Tôi đang suy nghĩ cụ thể của NET ở đây, nhưng các ví dụ chung là tốt.Chủ đề so với ThreadPool

Trả lời

99

hồ bơi Ðề tài sẽ đem lại lợi ích cho các hoạt động thường xuyên và tương đối ngắn bởi

  • Dùng lại bài đã được tạo ra thay vì tạo ra những cái mới (một quá trình tốn kém)
  • Điều chỉnh tiết tỷ lệ tạo thread khi có một loạt yêu cầu cho các mục công việc mới (tôi tin rằng điều này chỉ có trong .NET 3.5)

    • Nếu bạn xếp hàng 100 tác vụ trong hồ bơi, nó sẽ chỉ sử dụng nhiều các chủ đề đã được tạo để phục vụ các yêu cầu này (ví dụ 10 yêu cầu). Các hồ bơi thread sẽ thực hiện kiểm tra thường xuyên (Tôi tin rằng mỗi 500ms trong 3,5 SP1) và nếu có hàng đợi nhiệm vụ, nó sẽ làm cho một sợi mới. Nếu nhiệm vụ của bạn nhanh, thì số lượng chủ đề mới sẽ nhỏ và tái sử dụng 10 hoặc nhiều luồng cho các tác vụ ngắn sẽ nhanh hơn so với việc tạo 100 chủ đề lên phía trước.

    • Nếu khối lượng công việc của bạn luôn có số lượng lớn yêu cầu nhóm luồng, thì nhóm chủ đề sẽ tự điều chỉnh khối lượng công việc của bạn bằng cách tạo thêm chủ đề trong nhóm theo quy trình trên để có số lượng luồng lớn hơn để quá trình yêu cầu

    • séc Here để biết thêm thông tin trong sâu về cách các chức năng bơi thread dưới mui xe

Tạo một new thread mình sẽ appr hơn opriate nếu công việc sẽ tương đối dài chạy (có thể là khoảng một hoặc hai giây, nhưng nó phụ thuộc vào tình hình cụ thể)

@Krzysztof - Chủ đề Hồ bơi chủ đề là chủ đề nền sẽ dừng lại khi sợi chính kết thúc. Chủ đề được tạo theo cách thủ công là nền trước theo mặc định (sẽ tiếp tục chạy sau khi chuỗi chính đã kết thúc), nhưng có thể được đặt thành nền trước khi gọi Bắt đầu trên chúng.

+5

Điều duy nhất tôi đang tự hỏi về là báo cáo kết quả sau từ MSDN (http://msdn.microsoft.com/en-us /library/1c9txz50.aspx) "Một chuỗi nền chỉ thực hiện khi số lượng các chuỗi tiền cảnh thực hiện nhỏ hơn số lượng bộ xử lý." Vì vậy, điều đó có nghĩa rằng khi chia làm việc giữa các lõi mà các chủ đề tiền cảnh được ưu tiên? – cdiggins

+1

➤ Bạn không thể hủy bỏ hoặc làm gián đoạn chuỗi từ nhóm chủ đề. ➤ Bạn không thể tham gia một chuỗi từ nhóm chủ đề. Để đạt được điều đó, bạn phải sử dụng một số cơ chế khác – Zinov

1

Lưu trữ cục bộ chủ đề không phải là một ý tưởng hay với các nhóm luồng. Nó cho chủ đề một "danh tính"; không phải tất cả các chủ đề đều bình đẳng nữa. Bây giờ thread thread đặc biệt hữu ích nếu bạn chỉ cần một loạt các chủ đề giống hệt nhau, sẵn sàng để làm công việc của bạn mà không cần tạo ra trên không.

2

Kiểm tra ở đây cho một chủ đề trước đó:

When should I not use the ThreadPool in .Net?

Tóm tắt là ThreadPool là tốt nếu bạn cần để đẻ trứng nhiều đề shortlived, trong khi sử dụng Chủ đề cung cấp cho bạn kiểm soát nhiều hơn một chút.

1

Nếu bạn cần nhiều chủ đề, bạn có thể muốn sử dụng ThreadPool. Họ tái sử dụng các chủ đề giúp bạn tiết kiệm chi phí cho việc tạo luồng.

Nếu bạn chỉ cần một chuỗi để hoàn thành công việc, Chủ đề có lẽ là dễ nhất.

7

cũng

new Thread().Start()

spawns chủ đề Foreground rằng sẽ không chết nếu bạn đóng chương trình của bạn. Chủ đề ThreadPool là chủ đề nền chết khi bạn đóng ứng dụng.

+11

Bạn luôn có thể đặt chủ đề thành nền. Chúng chỉ là nền trước theo mặc định. –

+0

Eric, làm thế nào để làm điều đó? –

+3

nemo: var t = new Thread (...); t.BackgroundThread = true; t.Start(); –

0

Nói chung (tôi chưa bao giờ sử dụng .NET), một nhóm luồng sẽ được sử dụng cho mục đích quản lý tài nguyên. Nó cho phép các ràng buộc được cấu hình vào phần mềm của bạn. Nó cũng có thể được thực hiện vì lý do hiệu suất, như tạo ra các chủ đề mới có thể tốn kém.

Cũng có thể có các lý do cụ thể của hệ thống. Trong Java (một lần nữa tôi không biết nếu điều này áp dụng cho .NET), người quản lý các chủ đề có thể áp dụng các biến chủ đề cụ thể khi mỗi luồng được kéo ra khỏi hồ bơi, và bỏ đặt chúng khi chúng được trả về (cách phổ biến để truyền một cái gì đó như một bản sắc).

Ràng buộc mẫu: Tôi chỉ có 10 kết nối db, vì vậy tôi chỉ cho phép 10 chuỗi công nhân truy cập cơ sở dữ liệu.

Điều này không có nghĩa là bạn không nên tạo chủ đề của riêng bạn, nhưng có những điều kiện theo đó sử dụng hồ bơi có ý nghĩa.

13

.NET quản lý threadpool: -

  • kích cỡ riêng của mình dựa trên khối lượng công việc hiện tại và phần cứng có sẵn
  • Có đề người lao động đề cổng hoàn thành (được đặc biệt sử dụng để phục vụ IO)
  • Được tối ưu hóa cho một số lượng lớn các hoạt động tương đối ngắn ngủi

Triển khai nhóm luồng khác ist có thể thích hợp hơn cho các hoạt động dài hạn.

Cụ thể, sử dụng nhóm chủ đề để ngăn ứng dụng của bạn tạo các chủ đề quá nhiều. Các tính năng quan trọng nhất của một threadpool là hàng đợi công việc. Đó là, một khi máy của bạn đủ bận rộn, threadpool sẽ xếp hàng các yêu cầu thay vì ngay lập tức sinh ra nhiều luồng hơn.

Vì vậy, nếu bạn sẽ tạo một số lượng nhỏ, giới hạn chuỗi tạo chúng. Nếu bạn không thể xác định trước bao nhiêu luồng có thể được tạo (ví dụ: chúng được tạo ra để đáp ứng với IO đến) và công việc của chúng sẽ tồn tại trong thời gian ngắn, hãy sử dụng threadpool. Nếu bạn không biết bao nhiêu, nhưng công việc của họ sẽ được chạy dài, không có gì trong nền tảng để giúp bạn - nhưng bạn có thể tìm thấy các triển khai thay thế threadpool phù hợp.

+0

Trong .NET, bạn có thể sử dụng các cổng hoàn chỉnh không có nhóm luồng không? Tôi cho rằng các phương thức I/O không đồng bộ là cách duy nhất (trong .NET) và chúng sử dụng pool thread – Karg

0

Sử dụng hồ bơi là một ý tưởng hay, nếu bạn không biết hoặc không thể kiểm soát số lượng chuỗi sẽ được tạo.

Chỉ gặp vấn đề với biểu mẫu sử dụng chuỗi để cập nhật một số trường từ cơ sở dữ liệu trên sự kiện thay đổi vị trí của điều khiển danh sách (tránh freez). Mất 5 phút để người dùng của tôi có lỗi từ cơ sở dữ liệu (quá nhiều kết nối với Access) vì anh ấy đang thay đổi vị trí danh sách quá nhanh ...

Tôi biết có cách khác để giải quyết vấn đề cơ bản (bao gồm không sử dụng quyền truy cập) nhưng việc gộp nhóm là một khởi đầu tốt.

1

Nhu cầu chính cho các chủ đề của chủ đề theadpool là xử lý các tác vụ ngắn mà dự kiến ​​sẽ hoàn thành gần như ngay lập tức. Trình xử lý ngắt phần cứng thường chạy trong một bối cảnh xếp chồng không phù hợp với mã không phải hạt nhân, nhưng trình xử lý ngắt phần cứng có thể phát hiện ra rằng gọi lại hoàn thành chế độ người dùng I/O sẽ được chạy càng sớm càng tốt. Tạo một chủ đề mới cho mục đích chạy một thứ như vậy sẽ là quá mức cần thiết. Có một vài chủ đề được tạo trước có thể được gửi đi để chạy các cuộc gọi lại hoàn thành I/O hoặc những thứ tương tự khác hiệu quả hơn nhiều.

Một khía cạnh quan trọng của các chủ đề đó là nếu các phương thức hoàn thành I/O luôn hoàn thành về cơ bản ngay lập tức và không bao giờ chặn và số lượng các chủ đề hiện đang chạy như vậy ít nhất bằng với số lượng bộ xử lý. cách bất kỳ thread khác có thể chạy trước khi một trong những phương pháp nói trên kết thúc sẽ là nếu một trong các phương pháp khác khối hoặc thời gian thực hiện của nó vượt quá một lát thời gian bình thường luồng; không phải của những người nên xảy ra rất thường xuyên nếu hồ bơi thread được sử dụng như dự định.

Nếu một phương pháp không thể dự kiến ​​thoát ra trong vòng 100ms hoặc lâu hơn khi bắt đầu thực thi, phương pháp nên được thực hiện thông qua một số phương tiện khác ngoài nhóm chủ đề chính. Nếu có nhiều nhiệm vụ để thực hiện CPU chuyên sâu nhưng sẽ không chặn, có thể hữu ích khi gửi chúng bằng một nhóm các luồng ứng dụng (một luồng cho mỗi lõi CPU) tách biệt với luồng chính "", vì sử dụng nhiều chủ đề hơn lõi sẽ phản tác dụng khi chạy các tác vụ không đòi hỏi nhiều CPU. Tuy nhiên, nếu một phương thức sẽ mất một giây hoặc lâu hơn để thực thi, và sẽ dành phần lớn thời gian của nó bị chặn, phương thức này có thể được chạy trong một chuỗi chuyên dụng và hầu như chắc chắn không được chạy trong một luồng thread-thread chính. Nếu một hoạt động dài hạn cần được kích hoạt bởi một thứ như I/O callback, một trong hai nên bắt đầu một luồng cho hoạt động dài hạn trước cuộc gọi lại và chờ nó trên một màn hình mà xung gọi lại, hoặc người nào khác có gọi lại khởi động một chủ đề mới để thực hiện các hoạt động trong khi thoát khỏi cuộc gọi lại, có hiệu quả trở về chủ đề riêng của mình để threadpool.

2

Tôi đã tò mò về việc sử dụng tài nguyên tương đối cho những điều này và chạy điểm chuẩn trên máy tính xách tay Intel i5 lõi kép 2012 của tôi sử dụng bản phát hành .net 4.0 trên windows 8. Thread Pools mất 0,035ms trung bình để bắt đầu từ Chủ đề trung bình 5.06ms. Nói cách khác Chủ đề trong hồ bơi bắt đầu nhanh hơn khoảng 300 lần đối với số lượng lớn các chủ đề ngắn ngủi. Ít nhất là trong chuỗi thử nghiệm (100-2000), tổng thời gian cho mỗi luồng có vẻ khá ổn định.

Đây là mã đã được quy chuẩn hóa:

for (int i = 0; i < ThreadCount; i++) { 
     Task.Run(() => { }); 
    } 

    for (int i = 0; i < ThreadCount; i++) { 
     var t = new Thread(() => { }); 
     t.Start(); 
    } 

enter image description here

+3

Tôi nghĩ đó là vì ThreadPool sử dụng lại các luồng đã tạo thay vì tạo các luồng mới.) – fabriciorissetto