VB.Net/Thread/Producer Consumer

Материал из VB Эксперт
Перейти к: навигация, поиск

Producer and Consumer with Synchronized Integer Buffer

" *************************************************************
" * (C) Copyright 2003 by Deitel & Associates, Inc.           *
" *     and Prentice Hall.                                    *
" * All Rights Reserved.                                      *
" *                                                           *
" * DISCLAIMER: The authors and publisher of this book have   *
" * used their best efforts in preparing the book. These      *
" * efforts include the development, research, and testing of *
" * the theories and programs to determine their              *
" * effectiveness. The authors and publisher make no warranty *
" * of any kind, expressed or implied, with regard to these   *
" * programs or to the documentation contained in these books.*
" * The authors and publisher shall not be liable in any event*
" * for incidental or consequential damages in connection     *
" * with, or arising out of, the furnishing, performance, or  *
" * use of these programs.                                    *
" *************************************************************

Imports System
Imports System.Threading
Public Class MainClass
   Shared Sub Main()
      " create shared object used by threads
      Dim holdInteger As New SynchronizedIntegerBuffer()
      " Random object used by each thread
      Dim randomObject As New Random()
      " create Producer and Consumer objects
      Dim producer As New CProducer(holdInteger, randomObject)
      Dim consumer As New CConsumer(holdInteger, randomObject)
      " create threads for producer and consumer  
      " set delegates for each thread
      Dim producerThread As New Thread(AddressOf producer.Produce)
      Dim consumerThread As New Thread(AddressOf consumer.Consume)
      " name each thread
      producerThread.Name = "Producer"
      consumerThread.Name = "Consumer"
      " start each thread
      producerThread.Start()
      consumerThread.Start()
   End Sub " Main
End Class
" Produces integers from 1 to 4 and places them in unsynchronized buffer.
Public Class CProducer
   Private sharedLocation As SynchronizedIntegerBuffer
   Private randomSleepTime As Random
   Public Sub New(ByVal sharedObject As _
      SynchronizedIntegerBuffer, ByVal randomObject As Random)
      sharedLocation = sharedObject
      randomSleepTime = randomObject
   End Sub
   Public Sub Produce()
      Dim count As Integer
      For count = 1 To 4
         Thread.Sleep(randomSleepTime.Next(3000))
         sharedLocation.Buffer = count
      Next
      Console.WriteLine(Thread.CurrentThread.Name & _
         " done producing." & vbCrLf & "Terminating " & _
         Thread.CurrentThread.Name & ".")
   End Sub
End Class
" Consumes 4 integers from unsynchronized buffer.
Public Class CConsumer
   Private sharedLocation As SynchronizedIntegerBuffer
   Private randomSleepTime As Random
   Public Sub New(ByVal sharedObject As _
      SynchronizedIntegerBuffer, ByVal randomObject As Random)
      sharedLocation = sharedObject
      randomSleepTime = randomObject
   End Sub " New
   Public Sub Consume()
      Dim count, sum As Integer
      For count = 1 To 4
         Thread.Sleep(randomSleepTime.Next(3000))
         sum += sharedLocation.Buffer
      Next
      Console.WriteLine(Thread.CurrentThread.Name & _
         " read values totaling: " & sum & "." & vbCrLf & _
         "Terminating " & Thread.CurrentThread.Name & ".")
   End Sub " Consume
End Class
" Synchronizes access to an Integer.
Public Class SynchronizedIntegerBuffer
   Private mBuffer As Integer = -1
   Private occupiedBufferCount As Integer
   Public Property Buffer() As Integer
      Get
         " obtain lock on this object
         Monitor.Enter(Me)
         If occupiedBufferCount = 0 Then
            Console.WriteLine(Thread.CurrentThread.Name & _
               " tries to read.")
            DisplayState("Buffer empty. " & _
               Thread.CurrentThread.Name & " waits.")
            Monitor.Wait(Me)
         End If
         occupiedBufferCount -= 1
         DisplayState(Thread.CurrentThread.Name & " reads " & _
            mBuffer)
         Monitor.Pulse(Me)
         " Get copy of buffer before releasing lock.
         " It is possible that the producer could be
         " assigned the processor immediately after the 
         " monitor is released and before the return
         " statement executes. In this case, the producer
         " would assign a new value to buffer before the
         " return statement returns the value to the 
         " consumer. Thus, the consumer would receive the
         " new value. Making a copy of buffer and 
         " returning the copy helps ensure that the
         " consumer receives the proper value.
         Dim bufferCopy As Integer = mBuffer
         " release lock on this object
         Monitor.Exit(Me)
         Return bufferCopy
      End Get
      Set(ByVal Value As Integer)
         " acquire lock for this object
         Monitor.Enter(Me)
         " if there are no empty locations, place invoking
         " thread in WaitSleepJoin state
         If occupiedBufferCount = 1 Then
            Console.WriteLine(Thread.CurrentThread.Name & _
               " tries to write.")
            DisplayState("Buffer full. " & _
               Thread.CurrentThread.Name & " waits.")
            Monitor.Wait(Me)
         End If
         " set new buffer value
         mBuffer = Value
         occupiedBufferCount += 1
         DisplayState(Thread.CurrentThread.Name & " writes " & _
            mBuffer)
         Monitor.Pulse(Me)
         Monitor.Exit(Me)
      End Set
   End Property
   Public Sub DisplayState(ByVal operation As String)
      Console.WriteLine("{0,-35}{1,-9}{2}" & vbCrLf, _
         operation, mBuffer, occupiedBufferCount)
   End Sub
End Class


Producer and Consumer with Unsynchronized Integer Buffer

Imports System
Imports System.Threading
Public Class MainClass
   Shared Sub Main()
      " create shared object used by threads
      Dim holdInteger As New UnsynchronizedIntegerBuffer()
      " Random object used by each thread
      Dim randomObject As New Random()
      " create Producer and Consumer objects
      Dim producer As New CProducer(holdInteger, randomObject)
      Dim consumer As New CConsumer(holdInteger, randomObject)
      " create threads for producer and consumer  
      " set delegates for each thread
      Dim producerThread As New Thread(AddressOf producer.Produce)
      Dim consumerThread As New Thread(AddressOf consumer.Consume)
      " name each thread
      producerThread.Name = "Producer"
      consumerThread.Name = "Consumer"
      " start each thread
      producerThread.Start()
      consumerThread.Start()
   End Sub " Main
End Class
" Produces integers from 1 to 4 and places them in unsynchronized buffer.
Public Class CProducer
   Private sharedLocation As UnsynchronizedIntegerBuffer
   Private randomSleepTime As Random
   Public Sub New(ByVal sharedObject As _
      UnsynchronizedIntegerBuffer, ByVal randomObject As Random)
      sharedLocation = sharedObject
      randomSleepTime = randomObject
   End Sub
   Public Sub Produce()
      Dim count As Integer
      For count = 1 To 4
         Thread.Sleep(randomSleepTime.Next(3000))
         sharedLocation.Buffer = count
      Next
      Console.WriteLine(Thread.CurrentThread.Name & _
         " done producing." & vbCrLf & "Terminating " & _
         Thread.CurrentThread.Name & ".")
   End Sub
End Class
" Consumes 4 integers from unsynchronized buffer.
Public Class CConsumer
   Private sharedLocation As UnsynchronizedIntegerBuffer
   Private randomSleepTime As Random
   Public Sub New(ByVal sharedObject As _
      UnsynchronizedIntegerBuffer, ByVal randomObject As Random)
      sharedLocation = sharedObject
      randomSleepTime = randomObject
   End Sub " New
   Public Sub Consume()
      Dim count, sum As Integer
      For count = 1 To 4
         Thread.Sleep(randomSleepTime.Next(3000))
         sum += sharedLocation.Buffer
      Next
      Console.WriteLine(Thread.CurrentThread.Name & _
         " read values totaling: " & sum & "." & vbCrLf & _
         "Terminating " & Thread.CurrentThread.Name & ".")
   End Sub " Consume
End Class
" Definition of a shared integer without synchronization mechanisms.
Public Class UnsynchronizedIntegerBuffer
   Private mBuffer As Integer = -1
   Property Buffer() As Integer
      Get
         Console.WriteLine(Thread.CurrentThread.Name & _
            " reads " & mBuffer)
         Return mBuffer
      End Get
      Set(ByVal Value As Integer)
         Console.WriteLine(Thread.CurrentThread.Name & _
            " writes " & Value)
         mBuffer = Value
      End Set
   End Property " Buffer
End Class


Thread Producer and Consumer

Imports System.Threading
Module Module1
    Public Buffer As Integer
    Public BufferEmpty As Boolean = True
    Public MonitorLock As Object = New Object()
    Sub Producer()
        Dim Value As Integer = 0
        Do
            Monitor.Enter(MonitorLock)
            If (BufferEmpty) Then
                BufferEmpty = False
                Buffer = Value
                If (Value = 0) Then
                    Value = 1
                Else
                    Value = 0
                End If
                Console.WriteLine("Producer: " & Buffer)
            End If
            Monitor.Exit(MonitorLock)
        Loop While (True)
    End Sub
    Sub Consumer()
        Dim Value As Integer
        Do
            Monitor.Enter(MonitorLock)
            If (Not BufferEmpty) Then
                BufferEmpty = True
                Thread.CurrentThread.Sleep(1000)
                Value = Buffer
                Console.WriteLine("Consumer: " & Value)
            End If
            Monitor.Exit(MonitorLock)
        Loop While (True)
    End Sub
    Sub Main()
        Dim ProducerThread As Thread
        Dim ConsumerThread As Thread
        ProducerThread = New Thread(AddressOf Producer)
        ConsumerThread = New Thread(AddressOf Consumer)
        ProducerThread.Start()
        ConsumerThread.Start()
    End Sub
End Module