【Java多线程 01】认识线程
作者:互联网
一、什么是线程
目前,基本上所有操作系统都支持多任务的执行,对计算机来说,每一个人物就是一个进程,而在每一个进程内部,都至少有一个线程正在运行。我们有时称线程是轻量级的进程。线程是程序执行的路径,每一个线程都拥有自己的局部变量表,程序计数器以及各自的生命周期。
二、线程的生命周期
线程的生命周期其实还是很好理解的,分为 New, Runnable, Running, Blocked, Terminated 五个阶段,包含了线程从创建、到运行、再到死亡的全过程。
1. New 状态
当我们用关键字new创建一个Thread对象时,线程处于New状态。本质上,这只是一个普通的Java对象。当然,我们调用start()方法就可以进入Runnable状态。
2. Runnable 状态
进入 Runnable 状态后,线程加入线程池等待CPU的调度。执行了,但没有完全执行。由于存在Running状态,所以不会直接进入Blocked或者Terminated状态。严格来说,Runnable只能意外终止或者进入Running。
3. Running 状态
Runnable状态或者CPU调度后,进入Running状态,开始运行线程的执行单元。
初始状态 | 转换状态 | 原因 |
Running | Runnable | CPU调度器轮询要求线程放弃执行 主动调用yield |
Running | Blocked | 调用sleep/wait/join方法 进行某个阻塞的IO操作 获取某个同步锁资源 |
Running | Terminated | 调用stop或者JVM Crash |
4. Blocked 状态
一个正在执行的线程在某些特殊情况下,如执行耗时的输入/输出操作时,会放弃CPU的使用权,进入阻塞状态。线程进入阻塞状态后,就不能进入排队队列。只有当引用阻塞的原因,被消除后,线程才可以进入就绪状态。
5. Terminated 状态
线程的run()方法正常执行完毕,线程抛出一个未捕获的异常或错误或者JVM崩溃,线程就进入死亡状态。一旦进入死亡状态,线程将不再拥有运行的资格,也不能转换为其他状态。
三、Java Thread类源码
1. 内部参数
public class Thread implements Runnable {
// 我们忽略一些目前不太重要的参数
// 线程名
private volatile String name;
// 优先级
private int priority;
// 是否是守护线程
private boolean daemon = false;
// 是否导入Runnable作为参数,如果target为空,就会执行run()方法,否则运行target
private Runnable target;
// 确定线程组
private ThreadGroup group;
// 类加载器,待补充
private ClassLoader contextClassLoader;
// 访问控制,待补充
private AccessControlContext inheritedAccessControlContext;
// 如果Thread没有定下名字,这个数字用来自动生成"Thread-1"这样子的名字。
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/*
* 线程栈的大小
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*/
private final long stackSize;
/*
* 线程 ID
*/
private final long tid;
/* For generating thread ID */
private static long threadSeqNumber;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/*
* Java thread status for tools, default indicates thread 'not yet started'
*/
private volatile int threadStatus;
...
}
2、创建线程
public class Thread implements Runnable {
...
/* 这个是私有的构造函数,公开的构造函数很多都是选取其中部分参数 */
private Thread(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
// 确定父进程
Thread parent = currentThread();
// 获取SecurityManager
SecurityManager security = System.getSecurityManager();
// 线程池逻辑段
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security manager doesn't have a strong opinion
on the matter, use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(
SecurityConstants.SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
this.tid = nextThreadID();
}
...
}
3、start() 方法
public class Thread implements Runnable{
...
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
// 如果线程状态不为NEW, 报错
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
// 放入线程池
group.add(this);
// 标记,还未开始
boolean started = false;
try {
// C/C++写的本地方法,真正开始运行逻辑
start0();
// 运行成功
started = true;
} finally {
try {
if (!started) {
// 线程启动失败
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
...
}
四、创建线程的方法
总共有两种方法创建线程。一种是创建一个Thread类的子类,这个子类应当重写run()方法。
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
运行方法:
PrimeThread p = new PrimeThread(143);
p.start();
另一种则是实现Runnable接口,并将其作为参数传递给Thread类。
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
运行方法:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
标签:Runnable,Java,parent,Thread,private,线程,minPrime,多线程 来源: https://blog.csdn.net/qq_43272626/article/details/117753853