Operating environment and tools

  • jdk1.8.0
  • MacOS 11.4
  • IDEA

The operating system can run multiple programs at the same time. For example, playing music while downloading files and browsing the web. The operating system allocates chunks of CPU time to each process, giving the impression of parallel processing.

A multithreaded program can perform multiple tasks at the same time. Typically, each task is called a thread, which is short for thread control. A program that can run more than one thread at the same time is a multithreaded program.

What are the differences between multithreading and multiprocessing?

The essential difference is that processes each have their own set of variables, whereas threads share data. Threads are lighter than processes, and it is less expensive to create and destroy a thread than to start a new process.

In practice, multithreading is very useful. For example, the application processes the user’s input command while accessing the data through the network.

In this article we introduce the Thread class in Java.

Thread

The Thread class belongs to the java.lang package.

To create a Thread, simply create a new Thread object and pass in a Runnable that implements the run() method. Call the start() method to start the thread.

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run(a) {
            System.out.println("rustfisher said: hello"); }}); t1.start();Copy the code

Java lambda

    Thread t1 = new Thread(() -> System.out.println("rustfisher said: hello"));
    t1.start();
Copy the code

Do not call the run() method directly. Calling the run() method directly does not start a new thread, but instead executes tasks directly in the current thread.

Let’s look at an example using the thread.sleep () method.

Thread t1 = new Thread(() -> {
    for (String a : "rustfisher said: hello".split("")) {
        try {
            Thread.sleep(100);
        } catch(InterruptedException e) { e.printStackTrace(); } System.out.print(a); }}); t1.start();Copy the code

The sleep(int) method causes the thread to sleep for a specified amount of time in milliseconds. Try-catch is required to catch InterruptedException.

Interrupt threads

When the run() method completes its last statement, either returns, or an uncaught exception occurs, the thread terminates.

Threads can also be terminated using the ThreadInterrupt method. When the interrupt method is called, the thread’s interrupt status is changed to true. Use isInterrupted() to check the interrupted status of a thread.

But if the thread is blocked, there is no way to detect the interrupt status. When an interrupt method is called on a blocked thread (sleep or wait), the blocking call is interrupted by InterruptedException.

The interrupted thread can decide how to respond to the interrupt. You can simply treat the interrupt as a termination request. For example, we actively catch InterruptedException.

Thread t2 = new Thread(() -> {
    for (String a : "rustfisher said: hello".split("")) {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Interrupted exit thread");
            return; } System.out.print(a); }}); t2.start();new Thread(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    t2.interrupt();
}).start();
Copy the code

This small example shows how to interrupt thread T2 with interrupt(). Once thread T2 catches InterruptedException in its run() method, it can do its own processing.

Thread state

Threads have six states, represented by the enumeration class State:

  • NEW (NEW created)
  • RUNNABLE
  • BLOCKED.
  • WAITING for
  • TIMED_WAITING
  • TERMINATED

The state of the thread can be obtained using the getState() method.

Newly created thread

When a thread is new, it is in the new (newly created) state before it has started running. There is still some work to be done before the thread can run.

Runnable thread

Once the start() method is called, the thread is in a RUNNABLE state. The call to start() does not guarantee that the thread will run immediately, but depends on the operating system.

Once a thread starts running, it is not always running. The operating system allows other threads to run. A runnable thread may or may not be running.

Blocked and waiting

When a thread is in a blocked or wait state, it is temporarily inactive. No code is run and consumes minimal resources. Until the thread scheduler reactivates it.

  • When a thread attempts to acquire an internal object lock that is held by another thread, the thread blocks. When the lock is released and the thread scheduler allows the thread to hold it, the thread becomes non-blocking.
  • When a thread waits for another thread to notify the scheduler, it enters the wait state by itself. For example, callObject.wait()orThread.join()Methods.
  • A method with a timeout parameter puts a thread into a timeout wait state. For example,Thread.sleep().Object.wait(long).Thread.join(long).Lock.tryLock(long time, TimeUnit unit)

The diagram above shows the transition between states.

Be terminated

Reason for termination:

  • The run method exits normally
  • The run method was terminated by an exception that was not caught

Thread attributes

Thread priority, daemons, thread groups, and handlers that handle uncaught exceptions.

Thread priority

In Java, each thread has a priority. By default, a thread inherits the priority of its parent thread. The setPriority(int) method can be used to set the priority. The maximum priority is MAX_PRIORITY = 10, the minimum priority is MIN_PRIORITY = 1, and the common priority is NORM_PRIORITY = 5. The thread scheduler has the opportunity to select a new thread and will select the thread with the highest priority.

Daemon thread

Call setDaemon(true) to switch to daemon threads. The purpose of daemon threads is to provide services to other threads. For example, timing threads. When only the daemons are left, the virtual machine exits.

Daemon threads should not access inherent resources such as files and databases.

No exception handler was caught

The run() method throws an uncaught exception, which is passed to a handler for uncaught exceptions before the thread dies. To use this processor, the need to implement the interface Thread. UncaughtExceptionHandler, and use setUncaughtExceptionHandler (Thread. UncaughtExceptionHandler) method to give it to the Thread.

Thread t3 = new Thread(() -> {
    try {
        Thread.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
        return;
    }
    int x = 0, y = 3;
    int z = y / x; // create an exception
});
t3.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t + "There are uncaught exceptions"); e.printStackTrace(); }}); t3.start();Copy the code

After running, the run() method throws the ArithmeticException exception

Thread [Thread - 0, 5, the main] have uncaught exception Java lang. ArithmeticException: / by zero at Main.lambda$main$0(Main.java:15) at java.lang.Thread.run(Thread.java:748)Copy the code

Can also use the static method Thread. SetDefaultUncaughtExceptionHandler (Thread. UncaughtExceptionHandler) to install a default processor in all threads. You can do some work in this default handler, such as logging.

A ThreadGroup represents a group of threads. Additional thread groups can also be included.

The ThreadGroup class implements the UncaughtExceptionHandler interface. Its uncaughtException(Thread T, Throwable E) method does the following

  • If the thread group has a parent thread groupuncaughtExceptionIs invoked.
  • Otherwise, ifThread.getDefaultUncaughtExceptionHandler()Returns a non-empty handler that is used.
  • Otherwise, nothing is done if the Throwable thrown is a ThreadDeath object.
  • Otherwise, the thread name andThrowableThe stack trace output toSystem.errOn.

Reference Books:

  • Core Java, Volume II – Advanced Features 7th Edition
  • Concurrent Programming in Java