Как можно избежать потоков? - PullRequest
6 голосов
/ 20 декабря 2008

В последнее время я много читал о том, что написание многопоточных приложений - огромная боль в шее, и достаточно узнал об этой теме, чтобы понять, хотя бы на каком-то уровне, почему это так.

Я читал, что использование методов функционального программирования может помочь облегчить некоторые из этих проблем, но я никогда не видел простого примера функционального кода, который бы работал одновременно. Итак, какие есть альтернативы использованию потоков? По крайней мере, какие есть способы абстрагировать их, чтобы вам не приходилось думать о таких вещах, как блокировка и о том, являются ли объекты конкретной библиотеки поточно-ориентированными.

Я знаю, что Google MapReduce должен помочь с этой проблемой, но я не видел краткого объяснения этого.

Хотя ниже я привожу конкретный пример, мне более любопытны общие приемы, чем решение этой конкретной проблемы (хотя использование примера для иллюстрации других приемов было бы полезно).

Я пришел к этому вопросу, когда написал простой веб-сканер в качестве учебного упражнения. Это работает довольно хорошо, но это медленно. Большая часть узких мест связана с загрузкой страниц. В настоящее время он является однопоточным и, следовательно, загружает только одну страницу за раз. Таким образом, если страницы можно загружать одновременно, это значительно ускорит процесс, даже если сканер будет работать на одном процессоре. Я решил использовать темы, чтобы решить проблему, но они меня пугают. Любые предложения о том, как добавить параллелизм к этому типу проблемы, не развязывая ужасный ночной кошмар?

Ответы [ 14 ]

0 голосов
/ 20 декабря 2008

Нити не следует избегать, и при этом они не являются "сложными". Функциональное программирование также не обязательно является ответом. .NET Framework делает многопоточность довольно простой. Немного подумав, вы сможете создавать разумные многопоточные программы.

Вот пример вашего веб-сканера (в VB.NET)


Imports System.Threading
Imports System.Net

Module modCrawler

    Class URLtoDest
        Public strURL As String
        Public strDest As String
        Public Sub New(ByVal _strURL As String, ByVal _strDest As String)
            strURL = _strURL
            strDest = _strDest
        End Sub
    End Class

    Class URLDownloader

        Public id As Integer
        Public url As URLtoDest

        Public Sub New(ByVal _url As URLtoDest)
            url = _url
        End Sub

        Public Sub Download()

            Using wc As New WebClient()
                wc.DownloadFile(url.strURL, url.strDest)
                Console.WriteLine("Thread Finished - " & id)
            End Using

        End Sub

    End Class

    Public Sub Download(ByVal ud As URLtoDest)
        Dim dldr As New URLDownloader(ud)
        Dim thrd As New Thread(AddressOf dldr.Download)
        dldr.id = thrd.ManagedThreadId
        thrd.SetApartmentState(ApartmentState.STA)
        thrd.IsBackground = False
        Console.WriteLine("Starting Thread - " & thrd.ManagedThreadId)
        thrd.Start()        
    End Sub

    Sub Main()

        Dim lstUD As New List(Of URLtoDest)

        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file0.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file1.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file2.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file3.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file4.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file5.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file6.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file7.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file8.txt"))
        lstUD.Add(New URLtoDest("/253212/kak-mozhno-izbezhat-potokov", "c:\file9.txt"))

        For Each ud As URLtoDest In lstUD
            Download(ud)
        Next

        ' you will see this message in the middle of the text
        ' pressing a key before all files are done downloading aborts the threads that aren't finished
        Console.WriteLine("Press any key to exit...")
        Console.ReadKey()

    End Sub

End Module

0 голосов
/ 20 декабря 2008

Для python это выглядит как интересный подход: http://members.verizon.net/olsongt/stackless/why_stackless.html#introduction

0 голосов
/ 20 декабря 2008

Вы можете посмотреть видео MSDN на языке F #: PDC 2008: введение в F #

Это включает в себя две вещи, которые вы ищете. (Функциональный + Асинхронный)

0 голосов
/ 20 декабря 2008

Один простой способ избежать многопоточности в вашем простом сценарии - это загрузка из разных процессов. Основной процесс вызовет другие процессы с параметрами, которые загрузят файлы в локальный каталог, а затем основной процесс сможет выполнить реальную работу.

Я не думаю, что есть какое-то простое решение этих проблем. Это не проблема потоков. Это параллелизм, который тормозит человеческий разум.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...