1.无处不在的线程
进程(Process)通俗而言就是指运行中的程序,线程又称为“轻量级进程”,是由进程“创建”的,同一进程创建的所有线程,共同使用该进程的所有资源;也就是说,线程不是计算机资源的“请求”者,即,不是资源竞争者!比如一个运行的Java程序就是一个进程。从操作系统的角度看,线程(Thread)是进程中可以独立执行的子任务。一个进程可以包含多个线程,同一个进程中的线程共享该进程中所申请到的资源,比如,内存空间等。从JVM的角度来看线程是进程中的一个组件(Component),它可以看作是执行Java代码的最小单位。Java程序中任何一段代码总是执行在某个确定的线程中的。
package com.stk.AboutJavaThread;
public class JavaThread {
public static void main(String[] args) {
System.out.println("The main method was executed by thread:"
+ Thread.currentThread().getName());
Stark stark = new Stark("Java Thread everywhere");
stark.run();
}
static class Stark implements Runnable {
private final String info;
public Stark(String info) {
this.info = info;
}
private void doSomething(String info) {
System.out.println("The doSomething method was executed by thread:"
+ Thread.currentThread().getName());
System.out.println("Do Something with " + info);
}
@Override
public void run() {
doSomething(info);
}
}
}
运行结果:
The main method was executed by thread:main
The doSomething method was executed by thread:main
Do Something with Java Thread everywhere
Java中的线程一般可以分为守护线程(Daemon thread)和用户线程(User Thread)。用户线程会阻止JVM的正常停止,也就是说,在JVM停止前,应用程序中的所有用户线程必须先停止完毕;否则JVM无法停止。而守护线程则不会影响JVM的正常停止,也就是说,如果应用程序中有守护线程正在运行也不会影响JVM的正常停止。因此,守护线程通常用于执行一些重要性不是很高的任务;比如,用于监视其他线程的运行情况。
2.进程的创建和执行
在Java语言中,一个线程就是一个java.lang.Thread类的实例,因此在Java语言中创建一个线程就是创建一个Thread类的实例,当然这离不开有关内存的分配。创建一个Thread实例与创建其他类的实例不同的是,JVM会为一个Thread实例分配两个调用栈(Call Stack)所需的内存空间。这两个调用栈一个用于跟踪Java代码间的调用关系,另一个用于跟踪对本地代码(即,Native代码,通常是C代码)的调用关系。
一个Thread实例通常对应两个线程。一个是JVM的线程(或称之为Java线程),另一个是与JVM中的线程相对应的依赖于JVM宿主机(即,运行JVM的主机)操作系统的本地(Native)线程。启动一个Java线程只需要调用相应的Thread实例的start()方法即可。线程启动后,当相应的线程被JVM的线程调度器调度到运行时,相应Thread实例的run()方法会被JVM调用。
package com.stk.JavaThreadCreateAndRun;
public class CreateThreadAndRun {
public static void main(String[] args) {
System.out.println("The main method was executed by thread:"
+ Thread.currentThread().getName());
Stark stark = new Stark("Java Thread everywhere");
//创建一个线程
Thread thread = new Thread(stark);
//设置线程名
thread.setName("A-Working-Thread");
//启动线程
thread.start();
}
static class Stark implements Runnable {
private final String info;
public Stark(String info) {
this.info = info;
}
private void doSomething(String info) {
System.out.println("The doSomething method was executed by thread:"
+ Thread.currentThread().getName());
System.out.println("Do Something with " + info);
}
@Override
public void run() {
doSomething(info);
}
}
}
运行结果:
The main method was executed by thread:main
The doSomething method was executed by thread:A-Working-Thread
Do Something with Java Thread everywhere
上述例子中,通过直接new一个Thread类实例来创建一个线程。Thread类的其中一个构造器支持传入一个java.lang.Runnable接口实例,当相应线程启动时该实例的run()方法会被JVM调用。
与示例(1-0)相比较,同样的Stark类的同一个方法doSomething()此时是由名为A-Working-Thread线程而非main线程负责执行。这是因为示例(1-0)中Stark类的run()方法由main线程所执行的main方法直接调用,而示例(1-1)中Stark类的run()方法并没有在代码中直接调用,而是由JVM通过其创建的线程(线程名为A-Working-Thread)进行调用。