前言
多线程想必大家都不会陌生。因为在日常使用和开发中,多线程的使用实在是太常见了。我们都知道,发明多线程的目的是为了更好的利用计算机的 CPU 资源。比如在一个进程中如果只有一个线程(也叫主线程),那么如果当这个线程因为某种原因阻塞(等待用户输入数据等情况)的时候,那么相对应的这个进程也让出了 CPU 资源并暂停执行了。试想一下,如果我们在一个进程中添加多个线程,那么当这个进程中某个线程阻塞的时候,其余线程还可以继续执行,做它们自己的工作,这样的话计算机的利用效率就提高了。这当然是一个最简单也是最常用的例子。下面来看一下 Java 中线程的基本概念
基本概念
在 Java 中,线程被封装在 Thread.java
类中,我们可以通过这个类提供的相关 API 对线程进行调控和操作。先来看看源码中对这个类的介绍(截取自 JDK_1.8 Thread.java
部分顶部注释):
/**
* A <i>thread</i> is a thread of execution in a program. The Java
* Virtual Machine allows an application to have multiple threads of
* execution running concurrently.
* <p>
* Every thread has a priority. Threads with higher priority are
* executed in preference to threads with lower priority. Each thread
* may or may not also be marked as a daemon. When code running in
* some thread creates a new <code>Thread</code> object, the new
* thread has its priority initially set equal to the priority of the
* creating thread, and is a daemon thread if and only if the
* creating thread is a daemon.
* <p>
* When a Java Virtual Machine starts up, there is usually a single
* non-daemon thread (which typically calls the method named
* <code>main</code> of some designated class). The Java Virtual
* Machine continues to execute threads until either of the following
* occurs:
* <ul>
* <li>The <code>exit</code> method of class <code>Runtime</code> has been
* called and the security manager has permitted the exit operation
* to take place.
* <li>All threads that are not daemon threads have died, either by
* returning from the call to the <code>run</code> method or by
* throwing an exception that propagates beyond the <code>run</code>
* method.
* </ul>
* <p>
*
* ......
*
* Every thread has a name for identification purposes. More than
* one thread may have the same name. If a name is not specified when
* a thread is created, a new name is generated for it.
* <p>
* ......
* /
大致意思是:
在一个程序中线程是可以执行的对象,Java 虚拟机允许在一个程序中有多个线程并发执行(同时执行)。
每个线程都有一个优先级,优先级高的线程会优先于优先级低的线程执行。每个线程也可以被标记为守护线程(后面会介绍),当在一个线程执行过程中如果创建了另一个新的线程,那么初始时这个新的线程的优先级和创建它的线程的优先级相同,另外,在守护线程中只能创建守护线程。
当虚拟机启动的时候,它会创建一个非守护线程(就是主线程),并且虚拟机会一直执行这个线程直到发生下面几种情况之一:
RunTime 类中的 exit 方法被调用并且安全管理器允许程序退出。
所有的非守护线程结束运行,这包括线程中 run 方法的返回或者在 run 方法执行过程中发生了一个异常。
每个线程都有一个名字用来标志这个线程,多个线程名字可以相同。如果一个线程在创建时没有为它指定一个名字,那么虚拟机会为它自动生成一个名字。
从上面那段话我们知道线程存在优先级的概念,每个线程都会有一个名字,并且线程可以分为守护线程和非守护线程,同时一个 Java 程序运行时会创建并执行一个主线程(运行 main 方法的线程)。
下面来看一下怎么创建一个线程:
public Thread(Runnable target) {
// 如果我们不指定线程的名字,那么虚拟机会根据当前已经创建的线程的数量来默认指定一个线程名
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
在 Thread.java
类源码中截取了两个常用的创建线程的方法,很明显,参数 target
就是创建的线程在运行执行的 Runnable 对象,而参数 name
就是我们为线程指定的名字。
在创建完线程之后,我们可以调用线程对象的start()
方法来开启一个线程(这个方法只能被调用一次),也可以通过 Thread
类提供的 setPriority(int newPriority)
方法来设置线程的优先级,系统已经给我们提供了几个线程的优先级:
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
如果你不指定线程的优先级,那么其默认的优先级为 NORM_PRIORITY
,线程的优先级越高,其越容易得到 CPU 资源。 请注意:优先级越高的线程只是越容易得到 CPU 资源,也就是说优先级可以理解成线程获取 CPU