基本概念
进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程:线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
以上来自百度百科,我个人的理解就是进程就是线程的基本组成单位,每个线程处理一个简单的任务,而进程就是由多个线程组成来共同完成任务的程序。
Thread和Runnable都是在java.lang包下面,其中Runnable是一个只有run方法的接口,而Thread则是Runnable的实现类
PS:本文是基于oracle的jdk 1.8.0_121
Thread的状态
- NEW
至今尚未启动的线程处于这种状态。 - RUNNABLE
正在 Java 虚拟机中执行的线程处于这种状态。 - BLOCKED
受阻塞并等待某个监视器锁的线程处于这种状态。 - WAITING
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。 - TIMED_WAITING
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。 - TERMINATED
已退出的线程处于这种状态。
详情可以看java.lang.Thread.State这个枚举类
如何创建线程
线程的创建可以通过一个类继承Thread然后重写run()方法,或者是继承Runnable接口实现run()方法。
第一种方法可以在构造对象之后直接调用父类的start()方法创建一个新的线程。
第二种方法需要构建一个实现Runnable接口的类的对象,然后把这个对象作为参数来构造一个Thread对象,再调用start()方法创建一个新的线程。
run和start方法的区别
根据Thread的源码
1. run只会在传入Thread中的target对象不为null的情况下,才会运行target的run方法。
2. 而start方法则是先判断threadStatus是否为0(0表示线程为NEW状态),若否则抛出异常。
然后将这个线程对象加入线程组中,接着调用native的start0方法。
如果调用失败,则将这个线程对象从线程组中移除,并将记录未启动线程数目的变量nUnstartedThreads自增。
如何安全地终止线程
至于为什么不使用Thread的stop、suspend和resume这个三个弃用的API,详情请看
http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
-
在线程内部通过一个变量控制线程的终止和资源的释放,不过遇到线程阻塞就可能会没法通过修改变量的值来终止线程
public class SafeStopThread implements Runnable{
/**
* 运行状态的标识位,默认为true,表示运行中;为false则表示为停止运行
*/
private volatile boolean running = true;
@Override
public void run() {
int i=0;
//获取当前线程对象
Thread thread=Thread.currentThread();
//判断标识位和线程是否被中断,只要有一个条件符合就停止运行
while(running){
System.out.println(++i);
}
System.out.println(thread.getName()+" Safe Stop");
}
public void stop(){
this.running=false;
}
} 通过Thread的isInterrupted()方法,在线程对象的run方法中通过这个方法的返回值来控制线程的终止。
ps:也可以结合两种方法来安全地终止线程,代码如下:
public class SafeStopThread implements Runnable{
/**
* 运行状态的标识位,默认为true,表示运行中;为false则表示为停止运行
*/
private volatile boolean running = true;
@Override
public void run() {
int i=0;
//获取当前线程对象
Thread thread=Thread.currentThread();
//判断标识位和线程是否被中断,只要有一个条件符合就停止运行
while(running && !thread.isInterrupted()){
System.out.println(++i);
}
System.out.println(thread.getName()+" Safe Stop");
}
public void stop(){
this.running=false;
}
}