Almost all paint programs that use AWT or swing require multiple threads. But multithreaded programs can cause many difficulties, and developers who just start programming often find themselves plagued by problems such as improper program behavior or deadlock.
In this article, we will explore the problems encountered when using multithreading and present solutions to common pitfalls.
What is a thread?
A program or process can contain multiple threads that can execute corresponding instructions according to the Code of the program. Multithreading seems to be performing their own work in parallel, just like running multiple processors on a single computer. When implementing multiple threads on multiprocessor computers, they can indeed work in parallel. Unlike processes, threads share an address space. That is, multiple threads can read and write the same variable or data structure.
When writing multithreaded program, you must be aware of whether each thread interferes with the work of other threads. You can view a program as an office, and if you don't need to share office resources or communicate with others, all employees will work independently and in parallel. A staff member is supposed to talk to other people if and only if the clerk is "listening" and they speak the same language. In addition, employees are only able to use the copier if it is idle and in a usable state (not only half of the copy work is done, no paper blocking, and so on). As you'll see in this article, the threads that work with each other in a Java program are like employees working in a well-organized organization.
In multithreaded programs, threads can be obtained from the ready queue and run on the available system CPUs. The operating system can move a thread from the processor to the ready or blocked queue, which can be considered a processor "suspend" the thread. Similarly, a Java virtual machine (JVM) can control the movement of a thread from the ready queue to the processor in a collaboration or preemptive model, so that the thread can begin executing its program code.
The collaborative threading model allows the thread to decide when to discard the processor to wait for other threads. The program developer can determine exactly when a thread will be suspended by another thread, allowing them to collaborate effectively with the other. The disadvantage is that some malicious or poorly written threads consume all available CPU time, causing other threads to "starve".
In a preemptive threading model, the operating system can interrupt threads at any time. It is usually interrupted after it has been in operation for a period of time (called a time slice). The result is that no thread can unfairly occupy the processor for a long time. However, the possibility of interrupting a thread at any time can cause additional trouble to the program developer. Also using the example of an office, suppose that a staff member uses the copier before another person, but the print job leaves at an unfinished time, and the other person then uses the copier, and the copier may also have information that was left by the former staff member. The preemptive threading model requires that threads share resources correctly, while the collaborative model requires threads to share execution time. Because the JVM specification does not specifically prescribe threading models, Java developers must write programs that can run correctly on both models. After understanding the threads and some aspects of communication between threads, we can see how to design the program for both of these models.
Threads and the Java language
To create a thread using the Java language, you can generate an object of the thread class (or its subclasses) and send the start () message to the object. (The program can send a start () message to any class object that derives from the Runnable interface.) The definition of each thread action is contained in the run () method of the Thread object. The Run method is equivalent to the main () method in the traditional program, and the thread runs until run () returns, at which point the thread dies.
Locked
Most applications require threads to communicate with each other to synchronize their actions. The easiest way to achieve synchronization in a Java program is to lock it. To prevent access to shared resources at the same time, threads can lock and unlock the resource before and after using the resource. Pretend to lock the copier, only one employee has the key at any one time. If you don't have a key, you can't use the copier. Locking a shared variable allows Java threads to communicate and synchronize quickly and easily. A line Chengjo a lock on an object to know that no other thread can access the object. Even in a preemptive model, no other thread can access the object until the locked thread wakes up, completes the work, and unlocks the lock. Threads that attempt to access a locked object usually go to sleep until the locked thread unlocks. Once the locks are opened, the sleep processes are awakened and moved to the ready queue.
In Java programming, all objects have locks. Threads can use the Synchronized keyword to obtain a lock. At any one time for an instance of a given class, a method or a synchronized block of code can only be executed by one thread. This is because the code requires a lock on the object before it is executed. To continue our analogy with copiers, we can simply synchronize the copy resources in order to avoid duplicating conflicts. As in the following code example, only one employee is allowed to use the copy resource at any one time. Modify the state of the copier by using the method (in the Copier object). This method is the synchronization method. Only one thread can execute the synchronization code in a Copier object, so employees who need to use the Copier object must wait in line.
class CopyMachine {
public synchronized void makeCopies(Document d, int nCopies) {
// only one thread executes this at a time
}
public void loadPaper() {
// multiple threads could access this at once!
synchronized(this) {
// only one thread accesses this at a time
// feel free to use shared resources, overwrite members, etc.
}
}
}