Java: several ways to control threads
Java: several ways to control threads
There are many ways to control threads. This paper makes a summary.
join()
The official explanation is concise and clear: waits for this thread to die, Obviously, for threads, who calls, who dies. For example: when calling the join () method of the B thread in the A thread, the A thread will be blocked until the execution of the B thread is finished.
The join () method has three specific steps:
//等待该线程消亡
public final void join()
//等待该线程消亡,只不过最多等millis毫秒。
public final synchronized void join(long millis)
//等待该线程消亡,只不过最多等millis毫秒+nanos纳秒(毫微秒)。
public final synchronized void join(long millis,int nanos)
Simply test it and understand it more deeply:
public static void main(String[] args) throws InterruptedException {
//创建线程
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
});
//启动线程
t.start();
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
//i为1时,主线程阻塞,等待线程t执行并消亡
if(i == 1)
t.join();
}
}
It should be noted that the thread of the join must have started.
sleep()
Sleep (long) is a static method in the thread class. The previous article talked about the differences between sleep (long) method and yield () method:
The sleep () method has two specific methods:
//让当前线程暂停millis毫秒,并进入阻塞。
public static native void sleep(long millis)
//让当前线程暂停millis毫秒+nanos纳秒(毫微秒),并进入阻塞
public static void sleep(long millis,int nanos)
Both methods are affected by the precision and accuracy of the system timer and thread scheduler.
Daemon thread
There are two types of threads in Java: user thread and daemon thread.
I thought of a picture in my mind. In the past, when games such as soul Douluo broke through, there was often a big boss surrounded by many "wage earners" little monsters. As long as the boss dies, all the soldiers are GG. As long as the boss is alive, the soldiers will fight all the time.
We can regard the boss as a user thread and the soldier as a guard thread. As long as a non daemon thread is still executing in the JVM instance, the daemon thread must work. When the last non daemon thread ends, the daemon thread ends with the JVM.
The well-known garbage collector is a typical daemon thread, and the main thread is a user thread.
Main methods
For a deeper understanding, you can simply test:
public static void main(String[] args) throws InterruptedException {
//创建线程对象
Thread t = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" : "+i);
}
}
});
//设置为守护线程
t.setDaemon(true);
//启动守护线程
t.start();
//为了更明显,主线程睡眠100毫秒
Thread.sleep(100);
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+" : "+i);
}
}
The test results are as follows:
In the current program, there are no other non daemon threads except the main thread. Therefore, after the main thread ends, all daemon threads will also end.
There is another point worth noting: if all non daemon threads end, the daemon thread will also end, and the code in the finally block in the daemon thread will not be executed (this can be checked by yourself). Therefore, you can't rely on the daemon thread to complete the cleaning or finishing work, because you don't know whether the daemon thread is still alive in the next second.
Need attention
priority
As we said, each thread in the ready state is scheduled to wait for resources according to a certain rule, which is the priority of the thread.
Refer to Java programming ideas for the following:
//线程可有的最小优先级
public final static int MIN_PRIORITY = 1;
//默认优先级
public final static int NORM_PRIORITY = 5;
//线程可有的最大优先级
public final static int MAX_PRIORITY = 10;
Conduct the test:
class PDemo implements Runnable {
@Override
public void run() {
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println(name + ":" + i);
}
}
}
Thread t1 = new Thread(new PDemo(),"A");
Thread t2 = new Thread(new PDemo(),"B");
//默认情况下,线程的优先级为5
System.out.println(t1.getPriority());//5
System.out.println(t2.getPriority());//5
//设置线程优先级
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
Abandon the three brothers
stop()
resume
suspend
Interrupt three brothers
interrupt()
Public void interrupt() is an instance method of thread class. It is used to interrupt a thread, but in fact, it only sets an "interrupt" flag (true) for the thread, and the thread will continue to run. Users can monitor the status of the thread and make corresponding processing.
The official document says that the thread calling interrupt () will set the flag bit to true. In addition, the processing is different in different situations:
But I tested it according to the following code. Both join () and sleep () can be tested successfully, but wait () can't test. I don't know what the problem is. The great God in the comment area can help!!
The following two have not been contacted at present and will have the opportunity to make a summary in the future:
interrupted()
Public static Boolean interrupted() is a static method. Calling the isinterrupted method of the current thread internally will reset the interrupt state of the current thread. That is, if the thread is set as the interrupt flag, the first call to this method will return true and reset the interrupt flag. The second call to this method will return false.
isInterrupted()
Public Boolean isinterrupted() is an instance method that tests whether the object of the current thread is interrupted without resetting the interrupt state of the current thread.
For the testing of these three methods, please refer to this blog, which is very detailed: https://blog.csdn.net/zhuyong7/article/details/80852884
Safe thread termination
For the following reference: the art of Java Concurrent Programming
As mentioned above, the interrupt () method only marks the thread as "interrupted" and does not really interrupt the thread. We can monitor the flag bit and deal with it accordingly. For example, we can control whether we need to stop the task and terminate the thread through interrupt operation and user-defined variables.
Define an internal thread class.
private static class Runner implements Runnable {
private long i;
//定义变量作为标识位,用volatile修饰,自身拥有可见性和原子性
private volatile boolean on = true;
@Override
public void run() {
//对自定义标识位以及中断标识进行校验
while (on && !Thread.currentThread().isInterrupted()) {
i++;
}
System.out.println("Count i = " + i);
}
//取消操作
public void cancel() {
on = false;
}
}
Gracefully interrupt or end a thread with an identification bit.
public static void main(String[] args) throws InterruptedException {
Runner one = new Runner();
Thread countThread = new Thread(one,"CountThread");
countThread.start();
//睡眠一秒,main线程对CountThread进行中断,使CountThread能够感知中断而结束
TimeUnit.SECONDS.sleep(1);
countThread.interrupt();
Runner two = new Runner();
countThread = new Thread(two,"CountThread");
countThread.start();
//睡眠一秒,main线程对Runner two进行取消,使CountThread能够感知on为false而结束
TimeUnit.SECONDS.sleep(1);
two.cancel();
}
Reference links: the art of Java Concurrent Programming, crazy Java handout