The Java language sets 10 levels of Thread priority (thread.min_priority through thread.max_priority). When two threads are in the Ready state at the same time, the thread with higher priority is more likely to be selected by the system for execution. (This is defined by Java, but implemented by the operating system, but is a matter for the JVM)
The thread implementation of Java depends on the virtual machine, and that is how the virtual machine provides the implementation. It’s usually kernel-mode threads, user-mode threads, and some combination of the two. It all depends on how the JVM is implemented, so in a broad sense, multithreaded implementations are not limited. So there is no unified, for C language multithreading implementation of many ways are.
However, for most of our mainstream JVMS, threads are kernel-based (problems: threads mapped to the operating system have a natural disadvantage of costly switching, scheduling, and a limited number of threads on the system), and the operating system has a 1:1 relationship with threads.
For example, the emerging Golang and Kotlin use user state. This thread based on user state is generally called Routine or Fiber, and all scheduling is implemented by the user. That is, for example, the operating system thread is dead, but threads are CPU-based, whereas coroutines are thread-based, for the same reason. A thread can run multiple coroutines, so it is up to the user to design how to schedule multiple coroutines on a thread. The default stack is 1M(can be set via -xSS), but coroutines can vary in size by user definition, so a thread can run hundreds of coroutines. On the operating system of multi-threaded implementation can be baidu (time slice algorithm), in fact, understand the coroutine nature also understand.
Another implementation is a combination of the two. Don’t tell.
So for developers, there is only the JVM specification and the Java specification. There is no such thing as absolute.
If you don’t understand the above paragraph, you can read the book understanding Java Virtual Machines in Depth. Read this article if you still don’t understand threads, coroutines, and fibers.
Here are the Java threads. Take you into the world of Java. If you haven’t seen some.
1. Thread
This is a Java thread-unique entry class, everything else is a wrapper, thread pool, whatever. Thread. runnable is actually an interface method that is called when the Thread starts. A callback function, so to speak.
instantiation
1. No arguments
public Thread(a) {
init(null.null."Thread-" + nextThreadNum(), 0);
}
Copy the code
2. Most commonly used
Target — The object whose run method is invoked when this thread is invoked. If null, this classes run method does nothing.
The target object’s run method is run when the thread starts, and if not, the class run method does nothing,
This is the one we use most often
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Copy the code
3. The most complete parameter
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
Copy the code
group : the thread group. If null and there is a security manager, the group is determined by SecurityManager.getThreadGroup(). If there is not a security manager or SecurityManager.getThreadGroup() returns null, the group is set to the current thread’s thread group.
Name – The name of the new thread
StackSize – The desired stack size for the new thread, or zero to indicate that this parameter is to be ignored.
Group – Thread group. If not, there is a SecurityManager, and the group is determined by the SecurityManager’s getThreadGroup() method, If there is no Security Manager, etc., set this group to the thread group of the current thread.
The target-runnable object’s run method is run when the thread starts. If not, the class does nothing.
Name – The name of the current thread
StackSize – the stackSize required by the new thread, or 0 means that this parameter is ignored. Setting 0 here will allow the JVM to manage automatically, and if we set it manually, it will result in StackOverflowError or stack too small, OutOfMemoryError or internal error
Core – start
In Java, the only way to start a Thread is to take a Thread instance and start it. Java threads are equivalent to system threads.
For some, the way to create a Thread is that any Thread that inherits or instantiates directly can create a Thread. But starting is a method entry called start. It’s the same as golang’s go keyword.
This is the JavaDOC for the start() method.
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread. The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method). It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
When the current thread starts executing, the JVM uses the run method that calls the current thread.
The result is that two threads execute concurrently (one is the thread that executes the start method (probably the main thread, which returns immediately after executing the start method) and one is the thread that you instantiate (which executes the run method).
We do not allow the start method to be called twice, which is not reasonable. The thread will not restart after it has executed. The thread will not restart after it has executed.
2. Daemon thread
final void setDaemon(boolean on)
Marks this thread as either a daemon thread or a user thread. The Java Virtual Machine exits when the only threads running are all daemon threads. This method must be invoked before the thread is started.
This method must be called before the thread starts, i.e. before the start() method.
public final void setDaemon(boolean on) {
// the current thread cannot modify this thread
checkAccess();
// After strat runs, the thread status changes to isAlive, and an exception is raised
if (isAlive()) {
throw new IllegalThreadStateException();
}
// Default is non-daemon thread
daemon = on;
}
Copy the code
Daemon threads are threads that provide a common service in the background while the program is running. For example, garbage collection threads are a good guardian and are not an integral part of the program.
In fact, for later development, service threads, especially thread pools, are generally set to Deamon, except for the main thread to use daemons as much as possible, the benefit is to control the JVM process shutdown. For Golang, the GoRoutine is essentially a daemon thread. So normally you run without locking or waiting, normally the direct process shuts down.
3. Thread status
Java threads are in six states. The language is common in new, runnable, and terminated.
Type:
NEW: Thread state for a Thread which has not yet been started.
RUNNABLE : Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may You are waiting for other resources from the operating system such as the processor. The first step is to prepare some resources, which are in the ready state, and then enter the real startup process, so the cost of starting a thread is relatively high.
BLOCKED
: Thread state for a thread blocked waiting for a monitor lock.(sync)
WAITING
: Thread state for a waiting thread. (Object.wait)
TIMED_WAITING
: Thread state for a waiting thread with a specified waiting time. (Sleep)
TERMINATED : Thread state for a terminated thread. The thread has completed execution.
First of all, how to check these states,
Both jStack and JConsole work with the JDK’s built-in tools. Otherwise, you can manually check the status. Open a thread to the current thread, then…. It’s too much trouble.
1. Thread.sleep(time)
Thread state for a waiting Thread with a specified waiting time. The specified Thread is in TIMED_WAITING.
2. Object.wait()
This is in a WAITING state. Is in an object lock, so is in wait.
The timeout is in TIMED_WAITING state
Name: Anthony Status: java.lang.object @3fTotal number of blocked TIMED_WAITING on 462b58:0, total number of waits:1
Copy the code
3. Unsafe.park()
The same is true for LockSupport. It’s based on Unsafe.
WAITING if you do not specify a WAITING time, WAITING is TIMED_WAITING
Name: anthony2 Status: TIMED_WAITING0, total number of waits:1
Copy the code
But the reason why this is different from the one above, where there is no waiting object, is because each thread has a Blocker object inside it. You need to set this object. Then the call to the park operation will be displayed
LockSupport.parkUntil(new Object(), System.currentTimeMillis() + 1111111L);
Copy the code
volatile Object parkBlocker;
Copy the code
4. synchronize
The synchronized code is fast, and the synchronized method is in a BLOCKED state.
We can use JConsole to see which thread holds the Anthony thread. Obviously the anthony-2 thread.
Name: Anthony Status: java.lang.object @18961BLOCKED on ED8, owner: Anthony -2Total number of blocks:1, total number of waits:0
Copy the code
To summarize, this is just one diagram, from the actual Java Virtual machine.
The difference between blocking and waiting
** The difference between a blocked state and a wait state: **
The “blocking state” is waiting to acquire an exclusive lock. This event occurs when another thread abandons the lock.
A “wait state” is one that waits for a certain amount of time, or wakeup action, to occur. The thread enters this state while the program is waiting to enter the synchronization zone.
4. How do I close the thread
1. The interrupt () method
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
// This method only tests if the current moment is interrupted. Remember that it's a moment in time, so thread.interrupt doesn't deal with this.
while(! Thread.currentThread().isInterrupted()) {try {
say();
// You must force an InterruptedException, the core of which is here.
} catch (InterruptedException e) {
// throw to stop the current thread
throw newRuntimeException(e.getMessage()); }}}); thread.start();// Run for 1S, then send an interrupt command.
TimeUnit.MILLISECONDS.sleep(1000);
thread.interrupt();
}
static void say(a) throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
System.out.printf("Thread : %s in %s.\n", Thread.currentThread().getName(), Thread.currentThread().getState());
}
Copy the code
Output:
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Thread : Thread-0 in RUNNABLE.
Exception in thread "Thread-0" java.lang.RuntimeException: sleep interrupted
at com.guava.TestCondition.lambda$main$0(TestCondition.java:23)
at java.lang.Thread.run(Thread.java:748)
Copy the code
2. throw new Exception()
public static void main(String[] args) {
new Thread(() -> {
int x = 1;
while (true) {
System.out.println(Thread.currentThread().getName() + ":" + x++);
if (x == 5) {
// Throw an exception
throw new RuntimeException("exception");
}
}
}).start();
}
Copy the code
The output
Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
Thread-0 : 4
Exception in thread "Thread-0" java.lang.RuntimeException: exception
at com.threadstatus.StopThreadByException.lambda$main$0(StopThreadByException.java:20)
at java.lang.Thread.run(Thread.java:748)
Copy the code
3. Set an identifier
Pay attention to visibility.
public class StopThreadWithFlag {
private static volatile boolean flag = true;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
int x = 1;
while (flag) {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":"+ x++); }}); thread.start(); thread.join(); flag =false; }}Copy the code
The result? Thread. Join will not stop because the main thread is not executing at all. So in this case, we need to switch roles, and the main thread executes, and the child thread executes.
public class StopThreadWithFlag {
private static volatile boolean flag = true;
public static void main(String[] args) throws InterruptedException {
int x = 1;
Thread thread = new Thread(() -> {
flag = false;
});
thread.start();
while (flag) {
System.out.println(Thread.currentThread().getName() + ":"+ x++); }}}Copy the code
Reference article: Understanding the Java Virtual Machine in depth.