Java notes-basic thread knowledge

Source: Internet
Author: User

Java notes-basic thread knowledge
Preface

A process is an instance of a program in execution. It is an independent unit for the operating system to allocate and schedule resources. A thread is a single program control flow in a process and the basic unit of CPU scheduling and dispatching. The process has independent memory space during execution, and the threads in the process can share the memory space of the process. In the world of Java, a process can have multiple threads for concurrent execution. multithreading is a way to implement concurrent tasks.

Thread creation and startup

1. Implement the java. lang. Runnable interface
To define a task executed by a thread, you must implement the Runnable interface and compile the run method.

public interface Runnable {    /**     * Starts executing the active part of the class' code. This method is     * called when a thread is started that has been created with a class which     * implements {@code Runnable}.     */    public void run();}

The following example uses the Runnable interface to simulate the countdown task before the rocket launch:

public class LiftOff implements Runnable {    private int countDown;    public LiftOff(int countDown) {        this.countDown = countDown;    }    private String status() {        return countDown > 0 ? String.valueOf(countDown) : "LiftOff!";    }    @Override    public void run() {        while (countDown-- > 0) {            System.out.println(status());        }    }}

2. Implement the java. util. concurrent. Callable Interface
The call method of the Callable interface can generate a return value after the task is executed. The following is the definition of the Callable interface:

public interface Callable
  
    {    /**     * Computes a result, or throws an exception if unable to do so.     *     * @return computed result     * @throws Exception if unable to compute a result     */    V call() throws Exception;}
  

You can use the submit method of the ExecutorService class to submit a task that implements the Callable interface. The submit method will generate a Future object, which is parameterized by the type of the result returned by the call method. You can use the isDone method to check whether the Future has been completed. If yes, you can call the get method to obtain the result. You can also directly call the get method to obtain the result without using the isDone Method for Detection. If the result is not ready yet, the get method will be blocked until the result is ready.

class TaskWithResult implements Callable
  
    {    private int id;    public TaskWithResult(int id) {        this.id = id;    }    @Override    public String call() throws Exception {        return "Result of TaskWithResult " + id;    }}public class CallableDemo {    public static void main(String[] args) {        ExecutorService exec = Executors.newCachedThreadPool();        // save Future object of submitted task        List
   
    > futureList = new CopyOnWriteArrayList<>();        for (int i = 0; i < 10; i++) {            futureList.add(exec.submit(new TaskWithResult(i)));        }        // waiting for all results        while (futureList.size() > 0) {            for (Future
    
      future : futureList) {                if (future.isDone()) {                    try {                        System.out.println(future.get());                    } catch (InterruptedException | ExecutionException e) {                        e.printStackTrace();                    } finally {                        futureList.remove(future);                    }                }            }        }        exec.shutdown();    }}
    
   
  

3. inherit the java. lang. Thread class
The constructor of the Thread class contains a Runnable task. The following is the constructor of the Thread class:

public Thread(Runnable runnable);public Thread(Runnable runnable, String threadName);public Thread(ThreadGroup group, Runnable runnable);public Thread(ThreadGroup group, Runnable runnable, String threadName);public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize);

Call the start method of the Thread class to start the Thread. The start method executes necessary initialization for the new Thread, and then calls the Runnable run method to start the task in the new Thread, the thread stops when the run method is executed.

public class BasicThreads {    public static void main(String[] args) {        Thread thread = new Thread(new LiftOff(10));        thread.start();    }}

In summary, Runnable and Callable are work units, while Thread acts as work units and execution mechanisms. In general, Runnable and Callable take precedence over Thread because they can gain more flexibility.

Thread status

At any time point, a thread can only be in one of the following six states:

    public enum State {        /**         * The thread has been created, but has never been started.         */        NEW,        /**         * The thread may be run.         */        RUNNABLE,        /**         * The thread is blocked and waiting for a lock.         */        BLOCKED,        /**         * The thread is waiting.         */        WAITING,        /**         * The thread is waiting for a specified amount of time.         */        TIMED_WAITING,        /**         * The thread has been terminated.         */        TERMINATED    }

1. new status
At this time, the thread has allocated necessary system resources and executed initialization. Then, the thread scheduler converts the thread to a running or blocking state.
2. Runnable status
The thread is running at this time or waits for the thread scheduler to allocate the time slice to it.
3. Blocked status
At this time, the thread is blocked because it needs to obtain an exclusive lock. The thread scheduler will not allocate time slices to the thread until the thread meets the conditions and enters the running state.
4. Waiting status
At this time, the thread will not be allocated a time slice. Wait until it is explicitly awakened by other threads.
The thread enters the waiting state from the runable status, which may be due to the following reasons:
[1] Call the Object. wait method without the Timeout parameter.
[2] Call the Thread. join method without the Timeout parameter.
[3] The thread is waiting for an I/O operation to complete.
5. Wait deadline (Timed_waiting) Status
At this time, the thread will not be allocated a time slice. If the thread has not been explicitly awakened by other threads after the deadline expires, the system will automatically wake up.
The thread enters the waiting period status from the runable status, which may be due to the following reasons:
[1] Call the Thread. sleep method.
[2] Call the Object. wait method with the Timeout parameter set.
[3] Call the Thread. join method with the Timeout parameter set.
6. Terminated status
The thread is no longer schedulable. Thread termination is usually returned from the run method, or the thread is interrupted.

Shows the relationship between various States of a thread:

The current state of the thread can be obtained through the getState method. The getState method is defined as follows:

    /**     * Returns the current state of the Thread. This method is useful for     * monitoring purposes.     *     * @return a {@link State} value.     */    public State getState() {        return State.values()[nativeGetStatus(hasBeenStarted)];    }

Thread Scheduling refers to the process in which the system allocates CPU usage for threads. There are two main Scheduling Methods: Collaborative Thread Scheduling and preemptible thread scheduling.
A multi-threaded system with Collaborative Scheduling is used. The thread execution time is controlled by the thread itself. Advantages of collaborative multithreading: The implementation is simple, and thread switching is requested only after the thread completes the task. The switching operation is known to the thread, so there is no too many-thread synchronization problem; its disadvantage is also obvious: the thread execution time is uncontrollable. If a thread is written incorrectly, the whole process may be blocked.
Preemptible multithreading each Thread will be allocated the execution time by the system, and Thread switching is not determined by the Thread itself (in Java, Thread. the yield method can give you the right to use the CPU, but there is no way to bypass the thread scheduler to get the right to use the CPU). Therefore, the execution time is controlled by the system, so there will be no problem that a thread will cause the entire process to block. Currently, Java uses a preemptible thread scheduling method.

Common thread Methods

1. sleep Method
The sleep method will suspend the execution of the current running thread for the specified time and give the CPU to other threads for use. However, the thread still keeps the object lock. Therefore, after the sleep method ends, the thread returns to the runable state.

public static void sleep(long time) throws InterruptedException;public static void sleep(long millis, int nanos) throws InterruptedException;

2. join Method
If thread A calls the join method of the target thread B, thread A is suspended until thread B ends. Alternatively, the timeout parameter is input when the join method is called. If the target thread has not expired yet, the join method will return.

public final void join() throws InterruptedException;public final void join(long millis) throws InterruptedException;public final void join(long millis, int nanos) throws InterruptedException;

3. yield Method
The yield method enables the current running thread to return to the running state, so that threads with the same or higher priorities have the opportunity to be scheduled for execution. Like the sleep method, the thread still keeps the object lock. Therefore, after the yield method is called, the thread returns to the runable state.

public static native void yield();

4. interrupt Method
The interrupt method sends an interrupt request to the thread. The action depends on the current state of the thread. If the thread has been blocked or tries to execute a blocking operation, setting the thread interruption status will throw InterruptedException. When an InterruptedException exception is thrown or the Thread. interrupted method is called, the interrupt status is cleared to prevent two notifications when a Thread is interrupted.

public void interrupt();

When the interrupt method is called on the thread, the only time when the interrupt occurs is that the thread must enter the blocking operation, or it is already in the blocking operation process. Sleep/wait/join/NIO blocking can be interrupted, and I/O blocking and synchronized synchronous blocking cannot be interrupted.

Background thread

A daemon thread is a thread that provides services in the background when the program is running. Background threads are not an indispensable part of the program. When all non-Background threads end, the process will terminate and all background processes in the process will end.
The setDaemon method can be called before the thread starts to set the thread as a background process. The isDaemon method can be used to test whether the thread belongs to the background thread. Any thread created by the background thread will be automatically set as the background thread. Example:

public class SimpleDaemons implements Runnable {    @Override    public void run() {        while (true) {            try {                TimeUnit.MILLISECONDS.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) throws Exception {        for (int i = 0; i < 10; i++) {            Thread daemon = new Thread(new SimpleDaemons());            // must call before start            daemon.setDaemon(true);            daemon.start();            System.out.println("Daemon or not: " + (daemon.isDaemon() ? " yes" : "not"));        }        System.out.println("All daemons started");        TimeUnit.MILLISECONDS.sleep(200);    }}

Background threads are also common. For example, Zygote has four background threads, namely HeapTaskDaemon, ReferenceQueueDaemon, and FinalizerDaemon ), finalizerWatchdogDaemon (termination method monitoring thread ).

Collaboration between threads

When multiple threads work together to complete some tasks, the threads need to collaborate with each other. The key issue of collaboration between threads is handshaking. This handshaking can be achieved through the wait and Y/policyall methods of the Object, it can also be implemented through the Condition object with await and signal methods provided by Java SE5.

1. wait and notify/notifyAll Methods
The wait method enables the thread to wait for a condition to detect changes. This condition is usually changed by another thread. When the wait method is called, the current thread enters the waiting state, and the lock on the object will be released. Therefore, other synchronized methods in this object can be called during the wait process.
The notify method can be used to wake up a thread that calls the wait method to enter the waiting state. The yyall method can be used to wake up all threads that call the wait method to enter the waiting state. Because multiple threads may be in the wait state on a single object, it is safer to use policyall than to call policy. Using Y instead of yyall is an optimization. Only one of the threads waiting for the same condition will be awakened. Therefore, if using notify, you must ensure that the appropriate thread is awakened.
Using an example in Java programming, we need to coordinate the waxing (wax) and polishing (buff) during car maintenance. First, we need to finish a layer of wax, then polish it, and continue to lay a layer of wax, then, continue polishing and cycle in sequence. The following example uses the wait and policyall methods to complete the collaboration between threads:

class Car {    private boolean waxOn = false;    public synchronized void waxed() {        // ready to buff        waxOn = true;        notifyAll();    }    public synchronized void buffed() {        // ready to wax        waxOn = false;        notifyAll();    }    public synchronized void waitForWaxing() throws InterruptedException {        while (!waxOn)            wait();    }    public synchronized void waitForBuffing() throws InterruptedException {        while (waxOn)            wait();    }}class WaxTask implements Runnable {    private Car car;    public WaxTask(Car car) {        this.car = car;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                System.out.println("Wax On!");                TimeUnit.MILLISECONDS.sleep(200);                car.waxed();                car.waitForBuffing();            }        } catch (InterruptedException e) {            System.out.println("Exiting via interrupt");        }        System.out.println("Ending Wax On task");    }}class BuffTask implements Runnable {    private Car car;    public BuffTask(Car car) {        this.car = car;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                car.waitForWaxing();                System.out.println("Wax Off!");                TimeUnit.MILLISECONDS.sleep(200);                car.buffed();            }        } catch (InterruptedException e) {            System.out.println("Exiting via interrupt");        }        System.out.println("Ending Wax Off task");    }}public class WaxBuff {    public static void main(String[] args) throws Exception {        Car car = new Car();        ExecutorService exec = Executors.newCachedThreadPool();        exec.execute(new WaxTask(car));        exec.execute(new BuffTask(car));        TimeUnit.SECONDS.sleep(3);        // interrupt all submitted tasks        exec.shutdownNow();    }}

Wait, policy, and policyall Methods belong to the methods in the base class Object. They can only be called in the synchronous method or synchronization control block. Otherwise, an IllegalMonitorStateException exception will be thrown when the program is running.

2. Lock and Condition objects
The Condition class provided by Java. util. concurrent class library of java SE5 can also be used for collaboration between threads. The conditional object await method is used to wait for a Condition to detect changes. When the external conditions change, call the signal method to wake up the suspended thread, or call the signalAll method to wake up all the threads suspended on this Condition.
The following describes how to replace synchronized with ReentrantLock and rewrite the vehicle maintenance process using the await and signalAll methods provided by the Condition class:

class Car {    private boolean waxOn = false;    private Lock lock = new ReentrantLock();    private Condition condition = lock.newCondition();    public void waxed() {        lock.lock();        try {            // ready to buff            waxOn = true;            condition.signalAll();        } finally {            lock.unlock();        }    }    public void buffed() {        lock.lock();        try {            // ready to wax            waxOn = false;            condition.signalAll();        } finally {            lock.unlock();        }    }    public void waitForWaxing() throws InterruptedException {        lock.lock();        try {            while (!waxOn) {                condition.await();            }        } finally {            lock.unlock();        }    }    public void waitForBuffing() throws InterruptedException {        lock.lock();        try {            while (waxOn)                condition.await();        } finally {            lock.unlock();        }    }}class WaxTask implements Runnable {    private Car car;    public WaxTask(Car car) {        this.car = car;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                System.out.println("Wax On!");                TimeUnit.MILLISECONDS.sleep(200);                car.waxed();                car.waitForBuffing();            }        } catch (InterruptedException e) {            System.out.println("Exiting via interrupt");        }        System.out.println("Ending Wax On task");    }}class BuffTask implements Runnable {    private Car car;    public BuffTask(Car car) {        this.car = car;    }    @Override    public void run() {        try {            while (!Thread.interrupted()) {                car.waitForWaxing();                System.out.println("Wax Off!");                TimeUnit.MILLISECONDS.sleep(200);                car.buffed();            }        } catch (InterruptedException e) {            System.out.println("Exiting via interrupt");        }        System.out.println("Ending Wax Off task");    }}public class WaxBuff {    public static void main(String[] args) throws Exception {        Car car = new Car();        ExecutorService exec = Executors.newCachedThreadPool();        exec.execute(new BuffTask(car));        exec.execute(new WaxTask(car));        TimeUnit.SECONDS.sleep(3);        // interrupt all submitted tasks        exec.shutdownNow();    }}

Obviously, it is difficult to use the above thread collaboration method correctly. Therefore, we should use a more advanced tool, such as Synchronizer. A synx is an object that allows threads to wait for another thread and coordinate the promotion between them. Commonly Used synx includes CountDownLatch, Semaphore, and CyclicBarrier.

Postscript

Java threads seem simple, but there are a lot of points worth attention in the actual use process. If you are a little careless, you may encounter strange problems. Therefore, you need to be very careful or even conservative when using the thread. The above is what I think the thread is worth organizing. For more information, see references.

References

1. Java programming ideology (version 4th)
2. deep understanding of Java virtual machines (version 2nd)
3. tive Java (version 2nd)

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.