From the school to A factory all the way sunshine vicissitudes of life

Please go to www.codercc.com

Pros and cons of concurrent programming

1. Create a thread

A Java program starts with the main() method and executes according to the established code logic. It appears that no other thread is involved, but in fact Java programs are inherently multithreaded and contain :(1) threads that distribute signals sent to the JVM; (2) The thread calling the Finalize method of objects; (3) Clear the Reference thread; (4) Main thread, the entry of user program. So, how to create a new thread in the user program, as long as there are three ways:

  1. Override the run method by inheriting Thread;

  2. By implementing the Runable interface;

  3. By implementing the Callable interface in these three ways, see the demo below.

    public class CreateThreadDemo { public static void main(String[] args) { //1. Thread Thread = new Thread() {@override public void run() {system.out.println (" Thread"); super.run(); }}; thread.start(); Thread thread1 = new Thread(new Runnable() {@override public void run() {Thread thread1 = new Thread(new Runnable() { System.out.println(" implement runable interface "); }}); thread1.start(); / / 3. Implement callable interface ExecutorService service = Executors. NewSingleThreadExecutor (); Future<String> future = service.submit(new Callable() { @Override public String call() throws Exception { return "By implementing the Callable interface "; }}); try { String result = future.get(); System.out.println(result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }}}Copy the code

There are three ways to create a thread:

  • Since Java cannot implement multiple interfaces through multiple inheritance, consider implementing interfaces as much as possible when creating threads.
  • Implementing the Callable interface, submitting to the ExecutorService returns the results of asynchronous execution, and Often, you can also use FutureTask(Callable Callable) to wrap Callable and FeatureTask to submit to the ExecutorsService. As shown in figure:

Since FeatureTask also implements the Runable interface, you can use the second method to create new threads.

  • You can use Executors to convert Runable to Callable by following the Following methods: Callable Callable (Runnable Task) or Callable Callable (Runnable Task).

    2. Thread status conversion

    This figure is from the book “The Art of Concurrent Programming in JAVA”. Threads transition between different states, as shown in the figure above. Wait (),join(), locksupport.lock (), wait(), wait(long timeout), wait(long timeout), Sleep (long),join(long), locksupport.parknanos (), locksupport.parkutil () added the timeout wait function, which means that the thread will enter TIMED_WAITING after calling these methods. When the timeout WAITING time reaches, the thread will switch to the Runable state. In addition, when WAITING and TIMED _WAITING are in the state, the thread can switch to the Runable state through object.notify (),Object.notifyAll() methods. When a thread is competing for resources, it enters the BLOCKED state while waiting to acquire the lock, and when the lock is acquired, it enters the Runable state. After the thread is TERMINATED, it enters the TERMINATED state. State transition is the life cycle of the thread. Another thing to note:

    • When a thread enters a synchronized method or block of synchronized code, it switches to the BLOCKED state, And using Java. Util. Concurrent. The locks the lock to lock the thread is WAITING or TIMED_WAITING state, because the lock will call the LockSupport method.

    Use a table to summarize the six states above.

    3. Basic operations on thread status

    In addition to creating a new thread, there are basic operations that a thread needs to perform during its lifetime. These operations can be used as a means of communication between threads, such as using interrupted notifications to enable interaction between threads, as described below.

    3.1. interrupted

    Interrupt can be understood as a flag bit of a thread, which indicates whether a running thread has been interrupted by another thread. Interrupts are like other threads greeting that thread. Other threads can interrupt this thread by calling its interrupt() method, and this thread can respond to its interruption by calling isInterrupted (). Alternatively, you can interrupt the current Thread by calling Thread’s static method interrupted (), which clears the interrupt flag bit. Note that the interrupt flag bit is cleared when InterruptedException is thrown, meaning that isInterrupted returns false.

    Take a look with specific examples below

    Public class InterruptDemo {public static void main(String[] args) throws InterruptedException {//sleepThread sleep 1000ms final Thread sleepThread = new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } super.run(); }}; BusyThread = new Thread() {@override public void run() {while (true); }}; sleepThread.start(); busyThread.start(); sleepThread.interrupt(); busyThread.interrupt(); while (sleepThread.isInterrupted()) ; System.out.println("sleepThread isInterrupted: " + sleepThread.isInterrupted()); System.out.println("busyThread isInterrupted: " + busyThread.isInterrupted()); }}Copy the code

    The output

    sleepThread isInterrupted: false busyThread isInterrupted: true

    Enable two threads named sleepThread and BusyThread. SleepThread sleeps for 1s and BusyThread executes an infinite loop. If the thread sleepThread throws InterruptedException and clears the flags, the busyThread does not.

    In addition, the same can be accomplished by way of interrupt the simple interaction between threads, while (sleepThread. The isInterrupted ()) said sleepThread will be monitored in the Main, once interrupt flag bit in the sleepThread. Namely sleepThread. The isInterrupted () returns false will continue to the Main thread will continue to perform. Therefore, interrupts can be seen as a convenient way to interact with threads. Terminating a thread by breaking a flag bit or flag bit gives you the opportunity to clean up resources, which is more elegant and safer than arbitrarily terminating a thread.

    3.2. The join

    The join methods between the threads can be seen as a way of collaboration, in many cases, a thread of input may be very dependent on the output of another thread, it’s like two good gay friend, a gay friends go ahead first suddenly saw another gay friend left behind, this time he will be in place to wait the gay friends, such as gay friends to catch up, just two people hand in hand. In fact, this kind of collaboration between threads is also true to real life. In the process of software development, after obtaining requirements from customers, requirements need to be decomposed by requirements analysts. At this time, product development will continue to follow up. If A thread instance A executes threadb.join (), it means that the current threadA waits for threadB to terminate before threadA continues. The following methods are provided for the join method:

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

    In addition to the join() method, the Thread class also provides a method for waiting out of time. If a Thread threadB has not finished waiting out of time, the threadA will continue executing after the timeout. Join method source key:

     while (isAlive()) {
        wait(0);
     }
    Copy the code

    When threadB exits, notifyAll() is called to notifyAll waiting threads. When threadB exits, isAlive() returns false. Here is a concrete example of how to use the join method:

    public class JoinDemo { public static void main(String[] args) { Thread previousThread = Thread.currentThread(); for (int i = 1; i <= 10; i++) { Thread curThread = new JoinThread(previousThread); curThread.start(); previousThread = curThread; } } static class JoinThread extends Thread { private Thread thread; public JoinThread(Thread thread) { this.thread = thread; } @Override public void run() { try { thread.join(); System.out.println(thread.getName() + " terminated."); } catch (InterruptedException e) { e.printStackTrace(); }}}}Copy the code

    The output is:

    main terminated. Thread-0 terminated. Thread-1 terminated. Thread-2 terminated. Thread-3 terminated. Thread-4 terminated. Thread-5 terminated. Thread-6 terminated. Thread-7 terminated. Thread-8 terminated.

    In the example above, one creates 10 threads, and each thread waits for the previous thread to finish before continuing. Can be commonly understood as a relay, the first thread passes the baton to the next thread, and then to the next thread……

    3.3 sleep

    The public static native void sleep(long millis) method lets the current Thread sleep at a specified time, depending on the processor’s timer and scheduler. Note that the sleep method does not lose the lock if the current thread acquires it. The sleep method is often compared to the Object.wait() method, which is often asked in interviews.

    sleep() VS wait()

    The main differences:

    1. The sleep() method is the static method of Thread, while wait is the Object instance method
    2. The wait() method must be called either in a synchronized method or in a synchronized block, that is, the object lock must have been acquired. The sleep() method does not have this limitation and can be used anywhere. In addition, the wait() method releases the held object lock, causing the thread to enter the wait pool and wait for the next resource acquisition. The sleep() method only frees the CPU and does not release the object lock;
    3. Sleep () method if again after sleep time to get the CPU time slice will continue, and wait () method must wait for the Object. Notift/Object notifyAll notification, will leave the waiting pool, and again the CPU time slice will continue.

    3.4 yield

    public static native void yield(); This is a static method, and once executed, it causes the current thread to relinquish CPU. However, it is important to note that relinquishing CPU does not mean that the current thread will stop running. The current thread will continue to run if it gains CPU time slices in the next race. In addition, the given time slice will only be allocated to threads of the same priority as the current thread. What is thread priority? Let’s talk about it in detail.

    Modern operating systems basically schedule running threads in the form of time division. The operating system will divide time slices and the threads will be allocated several time slices. When the current time slice is used up, thread scheduling will occur and wait for the next allocation. The amount of time a thread allocates determines how much processor resources it uses, and thread priority is a thread attribute that determines how much or how little processor resources a thread needs to allocate.

    In Java programs, Priority is controlled by an integer member variable Priority, which ranges from 1 to 10. The **setPriority(int)** method can be set when building threads. The default priority is 5. Threads with higher priority get the processor timeslice first than threads with lower priority. Note that thread planning varies across JVMS and operating systems, with some operating systems even ignoring thread priority Settings.

    It is also important to note that sleep() and yield() both yield processor resources to the current thread. The difference is that sleep() yields a timeslath that other threads can compete for, i.e., each thread has a chance to obtain the timeslath that the current thread yields. The yield() method allows only threads with the same priority as the current thread to get the free CPU slice.

    4. Daemon threads

    Daemons are special threads that, as their name suggests, act as guardians of the system, silently guarding system services in the background, such as garbage collection threads, which can be understood by JIT threads. Corresponding to it is the user thread, the user thread can be considered as the system’s worker thread, it will complete the entire system’s business operations. When the user thread is finished, it means that the whole system’s business tasks are finished. Therefore, the system has no objects to guard, and the daemon thread will retire naturally. When a Java application has only daemon threads, the virtual machine will exit naturally. Here is a simple example to illustrate the use of Daemon threads.

    public class DaemonDemo { public static void main(String[] args) { Thread daemonThread = new Thread(new Runnable() { @Override public void run() { while (true) { try { System.out.println("i am alive"); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("finally block"); }}}}); daemonThread.setDaemon(true); daemonThread.start(); Thread.sleep(800); try {thread.sleep (800); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

    The output is:

    i am alive finally block i am alive

    In the example above, the daemodThread run method is a while loop that keeps printing, but when the main thread ends, the daemonThread exits, so there is no loop. The main thread sleeps for 800ms to ensure that the daemonThread can have a chance of time slice, that is to say, it can normally execute a printing operation of “I am alive” and a finally block operation. After the main thread ends, the daemonThread exits, printing only “I am alive” and not the finnal block. Therefore, it is important to note that the daemon thread does not execute the code in the Finnaly block when exiting, so it is not safe to perform operations such as freeing resources in the Finnaly block

    Threads can be set as daemons by setDaemon(true). Also note that the daemons must be set before the start() method, otherwise a message will be reported

    Exception in thread “main” java.lang.IllegalThreadStateException at java.lang.Thread.setDaemon(Thread.java:1365) at learn.DaemonDemo.main(DaemonDemo.java:19)

    Such an exception, but the thread will still execute, but as a normal user thread.