Java multi-thread programming, java multi-thread programming example

Source: Internet
Author: User

Java multi-thread programming, java multi-thread programming example

Notes for learning Java !!!

If you have any questions or want to obtain learning resources during the learning process, join the Java learning exchange group with the group number 618528494.Let's learn Java together!

I. Advantages and Disadvantages of Multithreading

Advantages of multithreading:

1) better resource utilization
2) program design is simpler in some cases
3) Faster program response

The cost of multithreading:

1) more complex design
Although some multi-threaded applications are simpler than single-threaded applications, others are generally more complex. This part of code requires special attention when multiple threads access Shared data. The interaction between threads is often very complicated. Errors generated by incorrect thread synchronization are very difficult to detect and reproduce to fix.

2) overhead of context switching
When the CPU switches from the execution thread to the execution of another thread, it needs to first store the local data of the current thread, program pointer, and so on, and then load the local data of the other thread, program pointer. This type of switch is called "context switch "). The CPU executes a thread in one context and switches to another context to execute another thread. Context switching is not cheap. If not necessary, context switching should be reduced.

2. Create java Multithreading

1. Create a subclass of Thread

Create an instance of the Thread subclass and override the run method. The run method will be executed after the start () method is called. Example:

public class MyThread extends Thread {   public void run(){     System.out.println("MyThread running");   }}MyThread myThread = new MyThread();myTread.start();

You can also create an anonymous subclass of the Thread as follows:

Thread thread = new Thread(){   public void run(){     System.out.println("Thread Running");   }};thread.start();

2. Implement the Runnable interface

The second way to write thread-based code is to create an instance of classes that implement the java. lang. Runnable interface. The methods in the instance can be called by the thread. The following is an example:

public class MyRunnable implements Runnable {   public void run(){    System.out.println("MyRunnable running");   }}Thread thread = new Thread(new MyRunnable());thread.start();

Similarly, you can create an anonymous class that implements the Runnable interface, as shown below:

Runnable myRunnable = new Runnable(){   public void run(){     System.out.println("Runnable running");   }}Thread thread = new Thread(myRunnable);thread.start();

Iii. Thread Security

Running multiple threads in the same program does not cause problems. The problem is that multiple threads access the same resource. Such as the same memory zone (variable, array, or object), system (Database, web services, etc.) or file. In fact, these problems can only occur when one or more threads write to these resources. As long as the resources do not change, it is safe for multiple threads to read the same resource.

When two threads compete for the same resource, if the access order to the resource is sensitive, there is a race condition. The Code section that causes the race condition to occur is called the critical section.

If the creation, use, and destruction of a resource are completed in the same thread and will never be out of the control of this thread, the use of this resource is thread-safe.

4. java synchronization Block

Synchronization blocks in Java are marked with synchronized. The synchronization block is synchronized to an object in Java. All synchronization blocks synchronized to an object can only be entered and operated by one thread at the same time. All other threads waiting to enter the synchronization block will be blocked until the threads executing the synchronization block exit.

There are four different synchronization blocks:

Instance method synchronization:

 public synchronized void add(int value){this.count += value; }

Java instance method synchronization is synchronized to the object that owns the method. In this way, the methods of each instance are synchronized to different objects, that is, the instance to which the method belongs. Only one thread can run in the instance method synchronization block. If multiple instances exist, one thread can perform operations in one instance synchronization block at a time. One instance and one thread.

Static Method synchronization:

public static synchronized void add(int value){ count += value; }

Static Method synchronization is performed on the class object where the method is located. Because a class in a Java Virtual Machine can only correspond to one class object, only one thread is allowed to execute static Synchronization Methods in the same class at the same time.

Synchronization block in the instance method:

public void add(int value){    synchronized(this){       this.count += value;    }  }

Note that the Java synchronization block constructor enclose objects with parentheses. In the preceding example, "this" is used to call the instance itself of the add method. The object enclosed in parentheses in the synchronization constructor is called the monitor object. The above Code uses the monitor Object synchronization, and synchronizes the instance method using the instance that calls the method itself as the monitor object. Only one thread can be executed in the Java method synchronized to the same monitor object at a time.

The following two examples synchronize the instance objects they call, so they are equivalent in the synchronous execution effect.

public class MyClass {   public synchronized void log1(String msg1, String msg2){      log.writeln(msg1);      log.writeln(msg2);   }   public void log2(String msg1, String msg2){      synchronized(this){         log.writeln(msg1);         log.writeln(msg2);      }   } }

Synchronization blocks in static methods:

public class MyClass {    public static synchronized void log1(String msg1, String msg2){       log.writeln(msg1);       log.writeln(msg2);    }    public static void log2(String msg1, String msg2){       synchronized(MyClass.class){          log.writeln(msg1);          log.writeln(msg2);       }    }  }

These two methods cannot be simultaneously accessed by threads. If the second synchronization block is not synchronized to the object MyClass. class. The two methods can be simultaneously accessed by the thread.

V. java thread Communication

The goal of thread communication is to enable threads to send signals to each other. On the other hand, thread communication enables threads to wait for signals from other threads.

Java has a built-in wait mechanism to allow threads to become non-running when waiting for signals. The java. lang. Object class defines three methods: wait (), Policy (), and policyall () to implement this wait mechanism.

Once a thread calls the wait () method of any object, it becomes non-running until another thread calls the notify () method of the same object. To call wait () or notify (), the thread must first obtain the Lock of that object. That is to say, the thread must call wait () or notify () in the synchronization block ().

The following is a shared object that uses the communication between threads implemented by wait () and notify:

public class MyWaitNotify{  MonitorObject myMonitorObject = new MonitorObject();  boolean wasSignalled = false;  public void doWait(){    synchronized(myMonitorObject){      while(!wasSignalled){        try{          myMonitorObject.wait();         } catch(InterruptedException e){...}      }      //clear signal and continue running.      wasSignalled = false;    }  }  public void doNotify(){    synchronized(myMonitorObject){      wasSignalled = true;      myMonitorObject.notify();    }  }}

Note the following:

1. Both the waiting thread and the wake-up thread call wait () and Y () in the synchronization block (). This is mandatory! If a thread does not hold an object lock, it cannot call wait (), Y (), or notifyAll (). Otherwise, an IllegalMonitorStateException is thrown.

2. Once the thread calls the wait () method, it releases the lock on the Monitored object. This allows other threads to call wait () or notify ().

3. To avoid signal loss, they must be stored in the signal class. The wasSignalled variable above.

4. False wakeup: for some inexplicable reason, the thread may wake up without calling y () and notifyAll. This is the so-called spurious wakeups ). To prevent false wakeup, the member variables that save the signal will be checked in a while loop, rather than in the if expression. Such a while loop is called a spin lock.

5. Do not call wait () in string constants or global objects (). MonitorObject cannot be a String constant or a global object. Each instance of mywaitpolicy has its own monitor object, instead of calling wait ()/notify () on an empty string ().

6. java locks

Since Java 5, the java. util. concurrent. locks package contains some locks, so you do not need to implement your own locks.

Common locks:

Java. util. concurrent. locks. Lock;
Java. util. concurrent. locks. ReentrantLock;
Java. util. concurrent. locks. ReadWriteLock;
Java. util. concurrent. locks. ReentrantReadWriteLock;

Simple implementation of a reentrant lock:

public class Lock {    boolean isLocked = false;    Thread  lockedBy = null;    int lockedCount = 0;    public synchronized void lock() throws InterruptedException{        Thread callingThread = Thread.currentThread();        while(isLocked && lockedBy != callingThread){            wait();        }        isLocked = true;        lockedCount++;        lockedBy = callingThread;    }    public synchronized void unlock(){        if(Thread.currentThread() == this.lockedBy){            lockedCount--;            if(lockedCount == 0){                isLocked = false;                notify();            }        }    }}

Note: Call unlock () in the finally statement ()

lock.lock();try{    //do critical section code, which may throw exception} finally {    lock.unlock();}

7. Other Synchronization Methods in java

Semaphores (Semaphore): java. util. concurrent. Semaphore

Blocking Queue: java. util. concurrent. BlockingQueue

public class BlockingQueue {    private List queue = new LinkedList();    private int limit = 10;    public BlockingQueue(int limit) {        this.limit = limit;    }    public synchronized void enqueue(Object item) throws InterruptedException {        while (this.queue.size() == this.limit) {            wait();        }        if (this.queue.size() == 0) {            notifyAll();        }        this.queue.add(item);    }    public synchronized Object dequeue() throws InterruptedException {        while (this.queue.size() == 0) {            wait();        }        if (this.queue.size() == this.limit) {            notifyAll();        }        return this.queue.remove(0);    }}

8. Thread Pool in java

Java provides four thread pools through Executors:

NewCachedThreadPool

Create a cacheable thread pool. If the thread pool size exceeds the thread required to process the task, some Idle threads (not executed in 60 seconds) will be reclaimed. When the number of tasks increases, this thread pool can intelligently add new threads to process tasks. This thread pool does not limit the thread pool size. The thread pool size depends entirely on the maximum thread size that can be created by the operating system (or JVM.

NewFixedThreadPool

Create a fixed thread pool. Each time a task is submitted, a thread is created until the thread reaches the maximum size of the thread pool. The size of the thread pool remains unchanged once it reaches the maximum value. If a thread ends due to an execution exception, the thread pool will add a new thread.

NewScheduledThreadPool

Creates an unlimited thread pool. This thread pool supports scheduled and periodic task execution.

NewSingleThreadExecutor

Creates a single-threaded thread pool. This thread pool supports scheduled and periodic task execution. This thread pool only has one thread working, which is equivalent to a single thread serial execution of all tasks. If this unique thread ends due to an exception, a new thread will replace it. This thread pool ensures that all tasks are executed in the order they are submitted.

Simple thread pool usage:

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main {    public static void main(String[] args) {        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();        for (int i = 0; i < 10; i++) {            final int index = i;            cachedThreadPool.execute(new Runnable() {                public void run() {                    System.out.println(index);                }            });        }    }}

Notes for learning Java !!!

If you have any questions or want to obtain learning resources during the learning process, join the Java learning exchange group with the group number 618528494.Let's learn Java together!

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.