How can threads communicate




















Multi-threading programming is a conceptual paradigm for programming where one can divide a program into two or more processes which can be run in parallel. There are two main advantages of multi-threading : Fist, program with multiple threads will, in general, result in better utilization of system resources, including the CPU, because another line of execution can grab the CPU when one line of execution is blocked.

Second, there are several problems better solved by multiple threads. For example, we can easily write a multi-threaded program to show animation, play music, display documents, and down load files from the network at the same time.

Java is a multi-threaded language. Java allows to write a program where more than one processes can be executed concurrently within the single program. Java's threads are often referred to as light weight threads, which means that they run in the same memory space. Because Java threads run in the same memory space, they can easily communicate among themselves because an object in one thread can call a method in another thread without any overhead from the operating system.

In this Tutorial we will learn how to do multi-threaded programming in Java. Basics of a thread As with the Java concepts, everything about thread are defined in a class Thread. The Thread class encapsulates all of the control one will need over threads. The Thread class is our only link to manage how threads behave. In this Section, we will learn about : how to create and run a thread, the life cycle of a thread, and the thread controlling methods.

Creating and Running a Thread There are two ways to define a thread: one is sub classing Thread and other is using the Runnable interface. Using the sub classing thread : With this method, we have to define a class as a sub class of the Thread class. This sub class should contain a body which will be defined by a method run.

This run method contains the actual task that the thread should perform. An instance of this sub class is then to be created by a new statement, followed by a call to the thread's start method to have the run method executed. Let us consider the Illustration 6. Illustration 6. In the above simple example, three threads all of them are of some type will be executed concurrently. Note that a thread can be directed to start its body by start method.

Using the Runnable interface : A second way to create threads is to make use of the Runnable interface. With this approach, first we have to implement the Runnable interface. This is illustrated with an example where two processes Brother and Sister will be executed simultaneously. Note : Note in the above example, how after implementing objects, their thread is created and their threads start execution. Also note that, a class instance with the run method defined within must be passed in as an argument in creating the thread instance so that when the start method of this Thread instance is called, Java run time knows which run method to execute.

This alternative method of creating a thread is useful when the class defining run method needs to be a sub class of other classes; the class can inherit all the data and methods of the super class. Life cycle of threads Each thread is always in one of five states, which is depicted in Figure 6. In this state, the local data members are allocated and initialized. Runnable : The Runnable state means that a thread is ready to run and is awaiting for the control of the processor, or in other words, threads are in this state in a queue and wait their turns to be executed.

Running : Running means that the thread has control of the processor, its code is currently being executed and thread will continue in this state until it get preempted by a higher priority thread, or until it relinquishes control. Blocked : A thread is Blocked means that it is being prevented from the Runnable or Running state and is waiting for some event in order for it to reenter the scheduling queue.

Dead : A thread is Dead when it finishes its execution or is stopped killed by another thread. Threads move from one state to another via a variety of means. The common methods for controlling a thread's state is shown in Figure 6. Below, we are to summarize these methods : start : A newborn thread with this method enter into Runnable state and Java run time create a system thread context and starts it running.

This method for a thread object can be called once only stop : This method causes a thread to stop immediately.

This is often an abrupt way to end a thread. It takes the thread and causes it to stop running and later on can be restored by calling it again. There is no gurantee that the thread will start running right way, since there might be a higher priority thread running already, but, resume causes the thread to become eligible for running.

After n milliseconds have expired, this thread will become elligible to run again. This is one way to ensure that the threads at lower priority do not get started. Other methods like wait , notify , join etc.

Let us illustrate the use of these method in a simple Application. Start Thread C Start Thread B Exit Thread C Illustration 6. There are number of methods defined in Thread which can be called for getting information about threads. Some of the most commonly used methods for thread's status are listed here : currentThread : The CurrentThread is a static method returns the Thread object which is the currently running thread.

This, therefore, identifies the thread with a string name. This is helpful for debugging multi-threaded programs. Following is the Illustration 6. Exit Thread A End of executuion Start Thread B Inter-thread communications allow threads to talk to or wait on each other. I have had success using a SwingWorker section 9. If the application is not Swing-based and you want to have different threads performing tasks in parallel and occasionally send messages to each other, consider ZeroMQ "The socket library that acts as a concurrency framework.

A thread can schedule work on it's own thread by sending itself a message. Your threads should be able to find and reference other threads from there. Whenever they are not waiting, they can be doing something at the same time. If they appear to be just waiting for each other it is likely you are better off with one thread. Using multiple threads is not always better. It is more likely to be a design issue with how you have broken down the problem.

Threads work best when there is a minimum of interaction between them. If they are highly dependent on each other you should consider using less threads. I would just have them move around and send messages to one another when they are in the same cell. Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams?

Collectives on Stack Overflow. Learn more. How can two threads communicate while both are running? Ask Question. Asked 9 years, 1 month ago. Active 9 years, 1 month ago.

Company Questions. Artificial Intelligence. Cloud Computing. Data Science. Angular 7. Machine Learning. Data Structures. Operating System. Computer Network. Compiler Design. Computer Organization.

Binary data transfer is represented by PipedOutputStream in the producer and PipedInputStream in the consumer , whereas character data transfer is represented by PipedWriter in the producer and PipedReader in the consumer.

Apart from the data transfer type, the two pipes have similar functionality. The lifetime of the pipe starts when either the writer or the reader thread establishes a connection, and it ends when the connection is closed.

The fundamental pipe life cycle can be summarized in three steps: setup, data transfer which can be repeated as long as the two threads want to exchange data , and disconnection. Here, the connection is established by the writer connecting to the reader.

The connection could just as well be established from the reader. Several constructors also implicitly set up a pipe.

The default buffer size is but is configurable from the consumer side of the pipe, as shown later:. Communication adheres to the consumer-producer pattern with a blocking mechanism. If the pipe is full, the write method will block until enough data has been read, and consequently removed from the pipe, to leave room for the data the writer is trying to add. The read method blocks whenever there is no data to read from the pipe.

You can cast the integer value back to a character. Calling flush after a write to the pipe notifies the consumer thread that new data is available.

This is useful from a performance perspective, because when the buffer is empty, the PipedReader uses a blocking call to wait with one-second timeout.

Hence, if the flush call is omitted, the consumer thread may delay the reading of data up to one second. By calling flush , the producer cuts short the wait in the consumer thread and allows data processing to continue immediately.

If the writer is closed, the pipe is disconnected but the data in the buffer can still be read. If the reader is closed, the buffer is cleared. This next example illustrates how pipes can process text that a user enters in an EditText. To keep the UI thread responsive, each character entered by the user is passed to a worker thread, which presumably handles some time-consuming processing:. Whenever a new character is added in the EditText , the character will be written to the pipe and read in the TextHandlerTask.

The consumer task is an infinite loop that reads a character from the pipe as soon as there is anything to read. The inner while-loop will block when calling read if the pipe is empty. Be careful when involving the UI thread with pipes, due to the possible blocking of calls if the pipe is either full producer blocks on its write call or empty consumer blocks on its read call.

Shared memory using the memory area known in programming as the heap is a common way to pass information between threads. All threads in an application can access the same address space within the process. Hence, if one thread writes a value on a variable in the shared memory, it can be read by all the other threads, as shown in Figure If a thread stores data as a local variable, no other thread can see it.

By storing it in shared memory, it can use the variables for communication and share work with other threads. Objects are stored in the shared memory if they are scoped as one of the following:.

Threads communicate through shared memory by defining instance and class fields that are accessible from multiple threads. While threads are communicating through the state variables on the shared memory, they could poll the state value to fetch changes to the state. The signaling mechanism varies depending on the synchronization type see Table The timeout parameters indicate how long the calling thread should wait before continuing the execution.

Upon a signal, the waiting thread continues execution. The calls thus support two different design patterns that use conditions: the notify or signal version wakes one thread, chosen at random, whereas the notifyAll or signalAll version wakes all threads waiting on the signal. Because multiple threads could receive the signal and one could enter the critical section before the others wake, receiving the signal does not guarantee that the correct state is achieved.

A waiting thread should apply a design pattern where it checks that the wanted condition is fulfilled before executing further. For example, if the shared state is protected with synchronization on the intrinsic lock, check the condition before calling wait :.

This pattern checks whether the condition predicate is fulfilled. If not, the thread blocks by calling wait. When another thread notifies on the monitor and the waiting thread wakes up, it checks again whether the condition has been fulfilled and, if not, it blocks again, waiting for a new signal. A very common Android use case is to create a worker thread from the UI thread and let the worker thread produce a result to be used by some UI element, so the UI thread should wait for the result.

However, the UI thread should not wait for a signal from a background thread, as it may block the UI thread. Instead, use the Android message passing mechanism discussed later. Thread signaling is a low-level, highly configurable mechanism that can be adapted to fit many use cases, but it may also be considered as the most error-prone technique.

Therefore, the Java platform builds high-level abstractions upon the thread signaling mechanism to solve one-directional handoff of arbitrary objects between threads. The producers hand off messages for the consumers to process. The intermediator between the threads is a queue with blocking behavior, i. BlockingQueue see Figure The BlockingQueue acts as the coordinator between the producer and consumer threads, wrapping a list implementation together with thread signaling.

The list contains a configurable number of elements that the producing threads fill with arbitrary data messages. On the other side, the consumer threads extract the messages in the order that they were enqueued and then process them. Coordination between the producers and consumers is necessary if they get out of sync, for example, if the producers hand off more messages than the consumers can handle.

So BlockingQueue uses thread conditions to ensure that producers cannot enqueue new messages if the BlockingQueue list is full, and that consumers know when there are messages to fetch.

Synchronization between the threads can be achieved with thread signaling, as Example: Consumer and Producer shows. But the BlockingQueue both blocks threads and signals the important state changes—i. The consumer-producer pattern implemented with the LinkedBlockingQueue -implementation is easily implemented by adding messages to the queue with put , and removing them with take , where put blocks the caller if the queue is full, and take blocks the caller if the queue is empty:.

So far, the thread communication options discussed have been regular Java, available in any Java application. The mechanisms—pipes, shared memory, and blocking queues—apply to Android applications but impose problems for the UI thread because of their tendency to block. The UI thread responsiveness is at risk when using mechanisms with blocking behavior, because that may occasionally hang the thread.

The most common thread communication use case in Android is between the UI thread and worker threads. Hence, the Android platform defines its own message passing mechanism for communication between threads. The UI thread can offload long tasks by sending data messages to be processed on background threads.

The message passing mechanism is a nonblocking consumer-producer pattern, where neither the producer thread nor the consumer thread will block during the message handoff. The message handling mechanism is fundamental in the Android platform and the API is located in the android. Messages are inserted by producer threads and processed by the consumer thread, as illustrated in Figure The following code implements what is probably one of the most common use cases.

The user presses a button on the screen that could trigger a long operation, such as a network operation. To avoid stalling the rendering of the UI, the long operation, represented here by a dummy doLongRunningOperation method, has to be executed on a worker thread.

Hence, the setup is merely one producer thread the UI thread and one consumer thread LooperThread. Our code sets up a message queue.

It handles the button click as usual in the onClick callback, which executes on the UI thread. In our implementation, the callback inserts a dummy message into the message queue. For sake of brevity, layouts and UI components have been left out of the example code:. Associate a Looper —and implicitly a MessageQueue —with the thread. Set up a Handler to be used by the producer for inserting messages in the queue. Here we use the default constructor so it will bind to the Looper of the current thread.

Hence, this Handler can created only after Looper. Callback that runs when the message has been dispatched to the worker thread. It checks the what parameter and then executes the long operation. Start dispatching messages from the message queue to the consumer thread.

This is a blocking call, so the worker thread will not finish. There is race condition between the setup of mHandler on a background thread and this usage on the UI thread.

Hence, validate that mHandler is available. Initialize a Message -object with the what argument arbitrarily set to 0. Terminate the background thread.

The call to Looper. The message queue is represented by the android. MessageQueue class. It is built with linked messages, constituting an unbound one-directional linked list. Producer threads insert messages that will later be dispatched to the consumer. The messages are sorted based on timestamps.

The pending message with the lowest timestamp value is first in line for dispatch to the consumer. However, a message is dispatched only if the timestamp value is less than the current time. If not, the dispatch will wait until the current time has passed the timestamp value.

Only one message has passed the dispatch barrier, which is the current time. If no message has passed the dispatch barrier when the Looper is ready to retrieve the next message, the consumer thread blocks.

Execution is resumed as soon as a message passes the dispatch barrier. The producers can insert new messages in the queue at any time and on any position in the queue. The insert position in the queue is based on the timestamp value. If a new message has the lowest timestamp value compared to the pending messages in the queue, it will occupy the first position in the queue, which is next to be dispatched.

Insertions always conform to the timestamp sorting order. Message insertion is discussed further in Handler.

If there is no message to process, a consumer thread has some idle time. For instance, Figure illustrates a time slot where the consumer thread is idle. By default, the consumer thread simply waits for new messages during idle time; but instead of waiting, the thread can be utilized to execute other tasks during these idle slots. This feature can be utilized to let noncritical tasks postpone their execution until no other messages are competing for execution time.

When a pending message has been dispatched, and no other message has passed the dispatch barrier, a time slot occurs where the consumer thread can be utilized for execution of other tasks. An application gets hold of this time slot with the android.



0コメント

  • 1000 / 1000