Thread thread

The Tortoise and the Hare:

package thread;

public class Tortoise implements Runnable{
    private int totalStep;
    private int step;
    public Tortoise(int totalStep) {
        this.totalStep=totalStep;
    }
    @Override
    public void run() {
        while(step<totalStep) {
            step++;
            System.out.printf("乌龟走了%d步。%n", step);
        }
    }

}
package thread;

public class Hara implements Runnable {
    private boolean[] flags = { true, false };
    private int totalStep;
    private int step;

    public Hara(int totalStep) {
        this.totalStep = totalStep;
    }

    @Override
    public void run() {
        while (step<totalStep) {
            boolean isHareSleep=flags[((int)(Math.random()*10))%2];//随机

            if(isHareSleep) {
                System.out.println("兔子睡着了");
            }else {
                step+=2;
                System.out.printf("兔子走了%d步。%n",step);
            }

        }

    }

}
package thread;

public class ThreadDemo {
    public static void main(String[] args) {
        new Thread(new Tortoise(10)).start();
        new Thread(new Hara(10)).start();
    }
}

From an abstract point of view and a developer's point of view, the JVM is a virtual computer that only installs a CPU called the main thread, which can execute the execution process defined by main(). If you want to add a CPU to the JVM, you need to create a Thread instance, and to start the additional CPU is to call the start() method of the Thread instance. The entry point of the additional CPU execution flow can be defined in the run() method of the Runnable interface. In fact, after the JVM is started, there is not only one main thread, but also threads such as garbage collection and memory management. However, this is the underlying mechanism. From the perspective of writing programs, the JVM does have only one main thread.
In addition to defining the process in the run() method of Runnable, another way to write a multi-threaded program is to inherit the Thead class and redefine the run() method. From the point of view of writing programs alone, the previous race of the tortoise and the hare can also be rewritten as follows:

public class Tortoise extends Thread{
    ....
    @Override
    public void run(){
    ....
    }
}

public class Hare extends Thread{
    ....
    @Override
    public void run(){
    ....
    }
}

transfer:

new Tortoise(10).start();
new Hare(10).start();

Thread itself also operates the Runnable interface:

@Override
public void run(){
    if(target!=null){
    target.run();
    }
}

After calling the start() method of the Thread instance, the run() method defined above will be executed. If the Runnable instance is specified when the Thread is created, it will be referenced by the target. Therefore, if you directly inherit Thread and redefine the run() method, of course, you can also execute the process. The advantage of operating the Runnable interface is that it is more flexible, and your class has the opportunity to inherit from other classes. If it inherits Thread, then the class is a kind of Thread, usually in order to directly use some of the methods defined in Thread, it will inherit Thread to operate.
In JDK8, since Lambda expressions can be used, and Runnable instances can be accepted when constructing Threads, in some cases where Threads must be constructed with anonymous class syntax, you can consider using Lambda expressions to operate Runnables, and then use them to create Threads:

new Thread(()->{//方法操作内容}).start();
  1. Daemon thread
    The main thread starts executing from the main() method and stops the JVM after the main() method ends. If additional threads are started in the main thread, the default will wait for all the threads to be started to finish executing the run() method before aborting the JVM. If a Thread is marked as a Daemon thread, when all non-Daemon threads are finished, the JVM will automatically terminate the setDaemon() method to set a non-Daemon thread starting from the main() method. You can use whether the
    thread Daemon thread:
package thread;

public class DaemonDemo {
    public static void main(String[] args) {
        Thread th = new Thread(() -> {
            while (true) {
                System.out.println("ggg...");
            }
        });
        th.setDaemon(true);
        th.start();
    }
}

If setDaemon() is not set to true, the program will continue to output without terminating, and the Deamon thread will end after the non-Deamon thread main() ends; use the isDaemon() method to determine whether the thread is a Daemon thread, all Daemon threads are by default The generated thread is also a Daemon thread, because basically a thread derived from a background service thread should also be generated for the background service, so when the thread that generates it stops, it should also stop along with it.
2. Thread basic state diagram
After calling the Thread instance start() method, the basic state is execution (Runnable), blocked (Blocked)) execution (unning). After instantiating Thread and executing start(), the thread enters the Runnable state. At this time, the thread has not actually started to execute the run() method. It must wait for the Scheduler to enter the CPU for execution before the thread executes the run() method and enters Running. condition. Threads seem to be executed at the same time, but in fact, at the same time point, a CPU can only execute one thread, but the CPU will keep switching threads, and the switching action is very fast, so it seems that the threads executing at the same time have their priority. , you can use the setpriority() method of Thread to set the priority. The value can be set from 1 (Thread. MIN_PRIORITY) to 10 ( Thread. MAX_PRIORITY ), the default is 5 ( Thread. NORM_PRIORLT ), and the set value from 1 to 10 is thrown Error: IllegalArgumentException. The higher the number, the higher the priority.
There are several situations that will cause the thread to enter the Blocked state. For example, the previous call to the Thread.sleep() method will cause the thread to enter the Blocked state (others include the blocking of competing object locks before entering synchronized, the blocking of calling wait(), etc.) ;Waiting for input and output to complete will also enter Blocked, and waiting for user input is an actual example. Using multi-threading, when a thread enters Blocked, it is often one of the ways to improve performance to allow another thread to be executed on the CPU (to become the Running state) to prevent the CPU from idling.
For example, the following program can specify the URL to download the web page to see the time spent without threads:

package thread;

import java.io.*;
import java.net.URL;

public class Download {
    public static void main(String[] args) throws Exception {
        URL[] urls = { new URL("https://blog.csdn.net/zkd758/article/details/80210270"),
                new URL("https://blog.csdn.net/zkd758/article/details/80143295"),
                new URL("https://blog.csdn.net/zkd758/article/details/80151669"),
                new URL("https://blog.csdn.net/zkd758/article/details/80037368"),
                new URL("https://blog.csdn.net/zkd758/article/details/80143295"),
                new URL("https://blog.csdn.net/zkd758/article/details/80152033") };
        String[] filenames = { "one.html", "two.html", "three.html", "four.html", "five.html", "six.html", };

        for (int i = 0; i <= urls.length; i++) {
            dump(urls[i].openStream(), new FileOutputStream(filenames[i]));
        }
    }

    public static void dump(InputStream src, OutputStream dest) throws IOException {
        try (InputStream input = new BufferedInputStream(src); OutputStream output = new BufferedOutputStream(dest)) {// 自动关闭
            byte[] data = new byte[1024];
            int length;
            while ((length = input.read(data)) != -1) {
                output.write(data, 0, length);
            }
        }
    }
}

Multithreading:

package thread;

import java.io.*;
import java.net.URL;

public class Download {
    public static void main(String[] args) throws Exception {
        URL[] urls = { new URL("https://blog.csdn.net/zkd758/article/details/80210270"),
                new URL("https://blog.csdn.net/zkd758/article/details/80143295"),
                new URL("https://blog.csdn.net/zkd758/article/details/80151669"),
                new URL("https://blog.csdn.net/zkd758/article/details/80037368"),
                new URL("https://blog.csdn.net/zkd758/article/details/80143295"),
                new URL("https://blog.csdn.net/zkd758/article/details/80152033") };
        String[] filenames = { "one.html", "two.html", "three.html", "four.html", "five.html", "six.html", };

        for (int i = 0; i <= urls.length; i++) {
            int index = i;
            new Thread(() -> {
                try {
                    dump(urls[index].openStream(), new FileOutputStream(filenames[index]));
                } catch (IOException e) {
                    throw new RuntimeException();
                }
            }).start();
        }

    }

    public static void dump(InputStream src, OutputStream dest) throws IOException {
        try (InputStream input = new BufferedInputStream(src); OutputStream output = new BufferedOutputStream(dest)) {// 自动关闭
            byte[] data = new byte[1024];
            int length;
            while ((length = input.read(data)) != -1) {
                output.write(data, 0, length);
            }
        }
    }
}
new FileOutputStream(filenames[index],ture)//ture后写入文件从文档原有内容后开始写入

In this example, during the for loop, a new Thread will be created and started to download the webpage. This will take significantly less time.
The thread enters the Blocked state due to input/output. After completing the input and output, it will return to the Runnable state and wait for the scheduler to be executed (Running state). A thread entering the Blocked state can be called by another thread's interrupt() method to leave the Blocked state.
For example, using Thread.sleep() will make the thread enter the Blocked state. If another thread calls the interrupt() method of the thread at this time, an
InterruptedException exception object will be thrown, which can make the thread "wake up":

package thread;

public class ThreadDemo {
    public static void main(String[] args) {
        Thread th=new Thread(){
            @Override
            public void run(){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("唤醒成功");
                }
            }
        };
        th.start();
        th.interrupt();
    }
}

join() to insert threads: When a thread joins another thread using join(), the thread must wait for the joined thread to finish executing before continuing:

package thread;

import static java.lang.System.out;

public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        out.println("Main线程开始...");
        Thread th = new Thread(() -> {
            out.println("th线程开始...");
            for (int i = 0; i < 2; i++) {
                out.println("th线程执行...");
            }
            out.println("th将结束...");
        });
        th.start();
        //th.join();
        out.println("main将结束...");
    }
}

If the thread in the program does not use join() to enter it into the main thread process, the description in the last line showing "main execution" will be executed first, because the thread uses sleep(), which gives the main thread a chance to get time to execute) .
Sometimes the added thread may be processed for too long. You do not want to wait endlessly for the thread to finish its work. You can specify a time in join(), such as join(10000). It is 10 seconds. If the added thread has not finished executing, the current thread can continue to execute the original workflow.
4. Stop the thread After the
thread completes the run() method, it will enter Dead. The thread that has entered Dead (or has already called the start() method) cannot call the start() method again, otherwise an
IllegalThreadstateException will be thrown. o
Defined on the thread class There is a stop() method, but it is marked as Deprecated. The API marked as Deprecated means that it has been defined in the past, but later because it will cause a certain problem, in order to ensure forward compatibility, these APIs are not directly eliminated, but it is not recommended to write new ones. program to use it again.
It is not recommended to use resume(), suspend(), destroy(), etc. of Thread, which may cause unexpected results. To stop the thread, you need to do it yourself:

public class Some implements Runnable{
    private volatile boolean isContinue=true;
    ...
    public void stop(){
    isContinue=false;
    }
    public void run(){
    while(isContinue){
            ...
        }
    }
}

To stop a thread simply call some's stop method. The flag is volatile, and the change of isContinue can be seen by the run() method, and will not continue to execute because the thread has called stop.
ThreadGroup
Each thread belongs to a thread group (ThreadGroup). If a thread is generated in the main() main process, the thread will belong to the main thread group. The name of the thread group to which the current thread belongs can be obtained by using the following program fragment: Thread.currentThread().getThreadGroup(). getName();
When each thread is generated, it will be classified into a certain thread group, depending on which group the thread is generated in. If not specified, it belongs to the thread group that generated the child thread. You can also specify a thread group by yourself. Once a thread belongs to a group, it cannot be changed.
The java.lang.ThreadGroup class can manage threads in a group. You can use the following methods to generate groups, and specify the group to belong to when generating threads:

ThreadGroup g1=new ThreadGroup("group1");
ThreadGroup g2=new ThreadGroup("group2");
Thread t1=new thread (g1,"group1的成员");
Thread t2=new thread (g2,"group2的成员");

Some methods of ThreadGroup can work on all threads in the group. For example, the interrupt() method can interrupt all threads in the group, and setMaxPriority) can set the maximum priority of all threads in the group.
If you want to get all the threads in the group at once, you can use the numerate() method. E.g:

Thread[] threadsnew Thread[threadGroupl.activeCount];
threadGroup1. enumeratethreads);

The activeCount() method gets the number of threads in the group, and the enumerate() method takes an array of Threads, which sets the thread object to each array index. There is an uncaughtException() method in ThreadGroup. When an exception occurs in a thread in the group and is not caught, the JVM will call this method for processing. If the ThreadGroup has a parent ThreadGroup, it will call the uncaughtException () method of the parent ThreadGroup, otherwise see if the exception is an instance of ThreadDeath. If so, do nothing, if not, call the exception printstrackTrace(). This method can be redefined if the exception handling behavior of the threads in the ThreadGroup must be defined. E.g:

package thread;

public class ThreadGroupDemo {
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("group") {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.printf("%s:%s%n", t.getName(), e.getMessage());
            }
        };
        Thread t = new Thread(tg, () -> {
            throw new RuntimeException("ggg");
        });
        t.start();
    }
}

The first parameter of the uncaughtException() method can obtain the thread instance where the exception occurred, and the second parameter can obtain the exception object. The example shows the name of the thread and the exception information.
If an exception occurs in ThreadGroup, the uncaughtException processing order is
If ohreadGroup has a parent ThreadGroup
, the parent
method
Otherwise, see if the Thread uses the
setUncaughtExceptionHandler
method to set the Thread.ncaught instance, and if so, its
uncaughtException ()
method will be called.
Otherwise, see if the exception is an
instance of ThreadDeath, if "yes", do nothing, if "no", call the exception's
printStrackTrace . Uncaught
exceptions will be handled by the Thread.UncaughtExceptionlon Handler instance set by the thread instance
setUncaughtException Handler
(). , followed by the thread's ThreadGroup, and then the default
Thread. UncaughtExceptionHandler o So for exceptions that are not caught by the thread itself, you can specify the handling method yourself:

package thread;

public class ThreadGroupDemo {
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("group") {

        Thread t = new Thread(tg, () -> {
            throw new RuntimeException("ggg");
        });
        t.start();

        Thread t2 = new Thread(tg, () -> {
            throw new RuntimeException("ggggggg");
        });
        t2.setUncaughtExceptionHandler((thread, throwable) -> {
            System.out.printf("%s:%s%n", thread.getName(), throwable.getMessage());
        });
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325494540&siteId=291194637