Thread generation 09, thread waiting, notification, and manual control of the number of threads, 09 thread

Source: Internet
Author: User
Tags crosstab

Thread generation 09, thread waiting, notification, and manual control of the number of threads, 09 thread


When a thread does not execute relevant actions until it receives notifications from another thread, you can consider using "Event Wait Handles )". The event wait handle mainly uses three classes: AutoResetEvent, ManualResetEvent, and CountdownEvent (. NET 4.0 ). This article includes:

 

※One thread waits for notifications from another thread.
※Two threads are waiting for mutual notification.
※One thread waits for notifications of multiple tasks in the queue.
※Manually controlling the number of threads


□One thread waits for notifications from another thread

 

The simplest scenario is that the thread that sends a signal only sends a notification once, and the waiting thread only receives the notification once. The waiting thread must have a waiting method, and the thread sending the signal must have a method for sending the signal. The AutoResetEvent class provides related methods.

    class Program
    {
// True indicates that the initial state is set to the terminated state.
        static EventWaitHandle _wait = new AutoResetEvent(false);
        static void Main(string[] args)
        {
            new Thread(Waiter).Start();
            Thread.Sleep(1000);
_ Wait. Set (); // sends an instruction
        }
        static void Waiter()
        {
Console. WriteLine ("everything is ready, waiting for instructions! ");
            _wait.WaitOne();
Console. WriteLine ("receive instruction ~~ ");
        }
    }

○ AutoResetEvent is like a crosstab chart at the entrance of the subway. If there is a ticket inserted, the event is pushed in, and only one person enters each time.
○ When the WaitOne method is called, it indicates that the thread has been blocked and is waiting for a signal, just like a passenger waiting for entry next to the crossbar.
○ When the Set method is called, it indicates that a signal is sent to the waiting thread, just like a crosstab chart receiving a ticket, passengers can pass through.

 

About AutoResetEvent:
○ You can also create an AutoResetEvent instance in this way: var auto = new EventWaitHandle (false, EventResetMode. AutoReset );
○ If the Set method is called, but no other thread calls the WaitOne method, this handle will always exist.
○ If the Set method is called multiple times but multiple threads call the WaitOne method, only one thread can receive signals one by one.
○ WaitOne also has several overload methods for receiving time interval parameters. You can use WaitOne (0) to test whether a wait handle is enabled.
○ Automatic Recovery of wait handles by GC

 

□Two threads notify each other to wait

 

There is another situation: the thread that sends a signal needs to send multiple notifications, and each time it needs to confirm that it waits for the thread to receive and then sends another notification. The general process is: thread A does things for the first time and sends A notification to enter the waiting state; thread B receives A notification, sends A notification, notifies thread A, and thread B enters the waiting state; thread A receives A notification from thread B, and then sends A notification for the second operation to enter the waiting status ...... two threads notify each other. Each thread is both a sender and a waiting person. The AutoResetEvent class can be used to solve this problem.

    class Program
    {
        static EventWaitHandle _ready = new AutoResetEvent(false);
        static EventWaitHandle _go = new AutoResetEvent(false);
        static readonly object o = new object();
        private static string _msg;
        static void Main(string[] args)
        {
            new Thread(DoSth).Start();
// Wait for the first time until another thread is ready
            _ready.WaitOne();
            lock (o)
            {
_ Msg = "hello ";
            }
            _go.Set();
// Second wait
            _ready.WaitOne();
            lock (o)
            {
_ Msg = ";
            }
            _go.Set();
// The third time
            _ready.WaitOne();
            lock (o)
            {
                _msg = null;
            }
            _go.Set();
        }
        static void DoSth()
        {
            while (true)
            {
                _ready.Set();
                _go.WaitOne();
                lock (o)
                {
                    if(_msg == null) return;
                    Console.WriteLine(_msg);
                }
            }
        }
    }

 

The thread in the Main method is called the Main thread, and the other thread is called the Working thread. The two threads work like this:

→ The main thread used the WaitOne method to wait for the first time and said, "The Working thread, I am waiting here"

 

→ The worker thread uses the Set Method and says, "the main thread, I will give you a signal. Prepare the first message." and use the WaitOne method to let yourself wait: "main thread, I have sent you a signal. I am waiting here to receive your first message." Let's take a look at the information that is not yet needed to be displayed.

 

→ The main thread receives a signal from the working thread, sets the first message, and then uses the Set Method to say, "The worker thread, my first message, sends you a signal ", I also used the WaitOne method to wait for the second time and said, "The Working thread, I have sent you a signal. I will wait here"

 

→ The worker thread uses the Set Method and says, "the main thread, I will give you a signal. Prepare the second message," and then uses the WaitOne method to let yourself wait: "The main thread, I have sent you a signal. I will wait here to prepare to receive your second message." Then, let's take a look at the information that needs to be displayed and print the information.

 

→ Analogy


□One thread waits for notifications of multiple tasks in the queue

 

When a waiting thread needs to execute multiple tasks one by one, the task can be placed in the queue.

 

Generally, "production/consumption queue" is called to achieve the above requirements ". The so-called "production" refers to putting multiple tasks into the queue, and the so-called "consumption" refers to executing the task when the tasks are listed one by one.

    class ProducerConsumerQueue : IDisposable
    {
        EventWaitHandle _ewh = new AutoResetEvent(false);
Private Thread _ worker; // wait for the Thread
        private readonly object _locker = new object();
Queue <string> _ tasks = new Queue <string> (); // task Queue
        public ProducerConsumerQueue()
        {
            _worker = new Thread(Work);
            _worker.Start();
        }
// The task enters the queue
        public void EnqueueTask(string task)
        {
            lock (_locker)
            {
                _tasks.Enqueue(task);
            }
// The task sends a signal once it enters the queue
            _ewh.Set();
        }
        void Work()
        {
            while (true)
            {
// Obtain the task from the queue
                string task = null;
                lock (_locker)
                {
                    if (_tasks.Count > 0)
                    {
                        task = _tasks.Dequeue();
                        if(task == null) return;
                    }
                }
// If the task is not null, simulate the execution of the task
                if (task != null)
                {
Console. WriteLine ("executing a thread task" + task );
Thread. Sleep (1000); // simulate the Thread Execution Process
                }
Else // If taks is null
                {
_ Ewh. WaitOne (); // waiting signal
                }
            }
        }
        public void Dispose()
        {
EnqueueTask (null); // sends a signal to exit the consumption thread
_ Worker. Join (); // Let the consumption thread stay
_ Ewh. Close (); // release event wait handle
        }
    }

○ The EnqueueTask method enables tasks to enter the queue. Each task that enters the queue sends a notification using the Set method. The process of generating a task is called "production"
○ The Wokr method keeps waiting when there is no task. When a task is displayed as a column, the WaitOne method is used to execute the task. The process of executing the task is called "consumption"
○ Create a constructor and start a waiting thread to keep the waiting thread working (through an infinite loop)

 

Client call.

    class Program
    {
        static void Main(string[] args)
        {
            using (ProducerConsumerQueue q = new ProducerConsumerQueue())
            {
                q.EnqueueTask("hello");
                for (int i = 0; i < 3; i++)
                {
Q. EnqueueTask ("report" + I );
                }
                q.EnqueueTask("world");
            }
        }
    }

 

□Manually control the number of threads

 

■ Use ManualResetEvent

If AutoResetEvent is compared to the Cross-pass entrance at the subway entrance, only one person can be allowed to enter at a time. ManualResetEvent can be seen as a company guard who can open the door at work time to allow multiple people to enter. The Set Method of ManualResetEvent is like opening the door. Multiple Threads can enter, and the Reset method is like closing the door, so the thread can no longer enter.

 

There are two ways to create a ManualResetEvent instance:

var manual1 = new ManualResetEvent (false);
var manual2 = new EventWaitHandle (false, EventResetMode.ManualReset);

 

The following is a simple application of EventWaitHandle:

    class Program
    {
        static EventWaitHandle handle = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            handle.Set();
            new Thread(SaySth).Start("Hello");
            new Thread(SaySth).Start("World");
            Thread.Sleep(2000);
            handle.Reset();
            new Thread(SaySth).Start("Again");
        }
        static void SaySth(object data)
        {            
            handle.WaitOne();
Console. WriteLine ("what I want to say is:" + data );
        }
    }

○ The Set method is equivalent to opening the door, and the two threads behind it are valid.
○ The Reset method is equivalent to shutting down, And the next thread is invalid.

 

■ Use CountdownEvent

CountdownEvent can also be regarded as a company guard, except that only a few people are allowed to enter when the work time is up.

    class Program
    {
        static CountdownEvent _countdown = new CountdownEvent(2);
        static void Main(string[] args)
        {
            new Thread(SaySth).Start("1");
            new Thread(SaySth).Start("2");           
        }
        static void SaySth(object o)
        {
            Thread.Sleep(1000);
            Console.WriteLine(o);
            _countdown.Signal();
        }
    }

○ Set the maximum number of threads allowed in the CountdownEvent constructor.
○ The Signal method indicates counting once.


Summary:

○ Using the AutoResetEvent class, one thread can wait for the notification from another thread. Two threads notify each other and one thread waits for the notification from multiple tasks in the queue.
○ Use the ManualResetEvent class to manually control the number of threads
○ CountdownEvent class, manual control of a fixed number of threads

 

 

The thread series includes:

Thread series 01, front-end thread, back-end thread, thread synchronization thread series 02, multiple threads simultaneously process a time-consuming task to save time thread series 03, multi-thread shared data, multi-thread data sharing

Thread series 04, passing data to the thread, thread naming, thread Exception Handling, thread pool thread series 05, manual end thread series 06, view the thread pool and Its thread series 07 through CLR code, use the lock statement block or Interlocked type method to ensure the data synchronization thread series 08 of the auto-Increment Variable, and implement various methods of thread lock, use lock, Montor, Mutex, Semaphore, and thread deadlock

Thread generation 09, thread waiting, notification, and manual control of the number of threads

Thread Generation 10, without explicitly calling the thread


C # a problem about serial port thread Utilization

I understand that this is a problem of inter-thread communication. When I receive a, the main thread creates a new thread and runs a function (such as WorkRun method) run in a new thread (such as thA). When the main thread receives B, it needs to notify thA to abort or change its running logic.
Statement of the startup thread:
Thread thA = new Thread (new ThreadStart (WorkRun ));
ThA. Start ();
In fact, there are only two possible scenarios. The first is that the main thread sends the stop thread command to the thA to stop the function; the other is to stop the function when it is executed to a certain point and wait for the main thread to give it a signal to decide what logic to execute.
1. If the thread is aborted, you only need to write
If (thA. ThreadState = ThreadState. Running)
{
ThA. Abort ();
}
2. If you need to stop and wait for the main thread command during running, use ManualResetEvent. ManualResetEvent allows the thread to send signals to each other. Generally, this communication involves the tasks that a thread must complete before other threads perform.

When a thread starts an activity (this activity must be completed before other threads can start), it calls Reset to put ManualResetEvent in a non-terminating State. This thread can be considered as controlling ManualResetEvent. The thread that calls WaitOne on ManualResetEvent will stop and wait for the signal. When the control thread completes the activity, it calls Set to send a signal waiting for the thread to continue. And release all the waiting threads.

Once it is terminated, ManualResetEvent remains terminated until it is manually reset. That is, the call to WaitOne will be returned immediately.

You can pass a Boolean value to the constructor to control the initial status of ManualResetEvent. If the initial status is terminated, the value is true; otherwise, the value is false.

ManualResetEvent can also be used with the staticWaitAll and WaitAny methods.

The following is an example (the following code example illustrates how to use a wait handle to send completion signals for different stages of complex digital computing. The calculation format is: Result = first item + second item + third item. Each item requires pre-calculation and final calculation using the calculated base .) :
Using System;
Using System. Threading;

Class CalculateTest
{
Static void Main ()
{
Calculate calc = new Calculate ();
Console. WriteLine ("Result = {0 }.",
Calc. Result (234). ToString ());
Console. WriteLine ("Result = {0 }.",
Calc. Result (55). ToString ());
}
}

Class Calculate
{
Double baseNumber, firstTerm, secondTerm, thirdTerm;
AutoResetEvent [] autoEvents;
ManualResetEvent manualEvent;

// Generate random numbers to simulate the actual calculations.
Random rand... the remaining full text>

What is the number of threads?

I. Thread Concept

In general, we call a Program that is being executed in a computer "Process" rather than "Program ). The so-called "Thread" is the control flow in a single sequence in the "process.

Most emerging operating systems, such as Mac, Windows NT, and Windows 95, adopt the concept of multithreading and regard threads as the basic execution unit. Thread is also a very important part of Java.

Even the simplest Applet is completed by multiple threads. In Java, the painting () and update () Methods of any Applet are called by AWT (Abstract Window Toolkit) plotting and event processing threads, the main milestone methods of Applet-init (), start (), stop () and destory ()-are called by the application that executes the Applet.

The concept of a single thread is nothing new. What is really interesting is that multiple threads are used in a program to complete different tasks at the same time. In some cases, Lightweig ht Process is used to replace threads. The similarity between threads and real processes lies in that they are a single sequential control flow. However, a thread is considered lightweight because it runs in the context of the entire program and can use the resources and environment shared by the entire program.

As a single sequential control flow, the threads in the running program must have some resources as necessary overhead. For example, an execution stack and a program counter must exist. Code executed in a thread only plays a role in its context, so "execution context" is used in some places to replace "Thread ".

Ii. Thread attributes

To correctly and effectively use a thread, you must understand all aspects of the thread and the Java real-time system. You must know how to provide the thread body, thread life cycle, scheduling thread, thread group, and Demo nThread ).

(1) thread body
All operations occur in the Thread body. In Java, the Thread body is the run () method inherited from the Thread class, or the run () method in the class that implements the Runnable interface. After a thread is generated and initialized, the real-time system calls its run () method. The code implementation in the run () method produces the thread behavior, which is the main part of the thread.

(2) thread status
The figure below shows the state of a thread at any time in its life cycle and the method that causes the state change. This is not a complete finite state diagram, but it basically summarizes the more interesting and common aspects of the thread. The following describes how to use the thread lifecycle as the data.

● New Thread)
A new Thread is generated when a Thread object is generated. When a thread is in the "New thread" state, it is only an empty thread object and has not been allocated to system resources. Therefore, you can only start or stop it. Any other operation will cause an exception.

● Runnable)
The start () method generates the resources required by the running thread, schedules the thread to execute, and calls the run () method of the thread. The thread is in a running state. This state is not called the running state because the thread does not always occupy the processor. In particular, for a PC with only one processor, only one runable thread can occupy the processor at any time. Java achieves multi-thread sharing to the processor through scheduling.

● Non-running state (Not Runnable)
When the following events occur, the thread enters the non-running state.
① The suspend () method is called;
② The sleep () method is called;
③ The thread uses wait () to wait for the condition variable;
④ The thread is in the I/O wait state.

● Dead)
When the run () method is returned, or another thread calls s... the remaining full text>

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.