前言:
这篇文章主要就什么是进程、什么是线程、线程的五个状态、线程的终止来展开讲解java多线程的知识点。
正文:
一、什么是进程?
进程是系统进行资源分配和调度的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
二、什么是线程?
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
三、进程和线程的关系
通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统内多个程序间并发执行的程度。
四、线程的状态
我们可以通过打开java.lang.thread的源码里看到,线程定义的6个状态
1.New: 尚未启动的线程的线程状态。
2.Runnable: 可运行线程的线程状态,等待CPU调度。
3.Blocked: 线程阻塞等待监视器锁定的线程状态。
4.Waiting:等待线程的线程状态。下列不带超时的方式:
Object.wait、Thread.join、LockSupport.park
5.Timed Waiting:具有指定等待时间的等待线程状态。下列带超时的方式
Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil
6. Terminated:线程终止的状态。线程正常完成执行或者出现异常。
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
这里我写个Demo,来看下状态的变换
public static void main(String[] args) throws InterruptedException {
//第一种状态切换 - 新建 -> 运行 -> 终止
System.out.println("######第一种状态切换 - 新建 -> 运行 -> 终止############################");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread1当前状态:"+Thread.currentThread().getState().toString());
System.out.println("thread1 执行了");
}
});
System.out.println("没调用start方法,thread1当前状态:"+thread1.getState().toString());
thread1.start();
Thread.sleep(2000L);//等待thread1执行结束,再看状态
System.out.println("等待两秒,再看thread1当前状态:"+thread1.getState().toString());
//thread1.start(); //TODO注意,线程终止之后,再进行调用,会抛出IllegalThreadStateException异常
}
运行的结果打印:
######第一种状态切换 - 新建 -> 运行 -> 终止############################
没调用start方法,thread1当前状态:NEW
thread1当前状态:RUNNABLE
thread1 执行了
等待两秒,再看thread1当前状态:TERMINATED
其他的状态,可以编写一下试试,有的文章里会写在可运行状态前有种状态叫做就绪状态是Runnable,运行时状态是Running,但是如果你打印线程当前的运行状态其实是Runnable。
四、线程的终止
1.不正确的终止方式
thread.stop方法终止线程,会导致线程不安全。通俗的说,即使你在run()方法的代码块里加上synchronized关键字,也无法保证原子性操作,因为stop会破会这个原子性,拦腰折断
public class StopThread extends Thread {
private int i = 0, j = 0;
@Override
public void run() {
synchronized (this) {
//增加同步锁,确保线程安全
++i;
try {
//休眠10秒,模拟耗时操作
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
++j;
}
}
public void print(){
System.out.println("i="+i+"j="+j);
}
public static void main(String[] args) throws InterruptedException {
StopThread thread = new StopThread();
thread.start();
//休眠1秒,确保i变量自增成功
Thread.sleep(1000);
thread.stop();//错误的终止
Thread.sleep(1000);
System.out.println(thread.isAlive());
while (thread.isAlive()){
//确保线程已经终止
}
thread.print();
}
运行结果:
false
i=1j=0
我们可以明显看到,i和j的结果不一样,破坏了 synchronized关键字同步效果。
2.正确的终止方式
2.1调用thread.interrupt()方法就可以正确终止线程。把上面的例子改成interrupt来终止线程,i与j的结果就保持一致。
public static void main(String[] args) throws InterruptedException {
StopThread thread = new StopThread();
thread.start();
//休眠1秒,确保i变量自增成功
Thread.sleep(1000);
hread.interrupt();//正确的终止
Thread.sleep(1000);
System.out.println(thread.isAlive());
while (thread.isAlive()){
//确保线程已经终止
}
thread.print();
}
运行后的结果:
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.study.oa.study.StopThread.run(StopThread.java:13)
false
i=1j=1
2.2 还可以用标志位来正确终止线程
public class Demo4 extends Thread{
public volatile static boolean flag=true;
public static void main(String[] args) throws InterruptedException {
new Thread(() ->{
try {
while (flag){//判断是否运行
System.out.println("运行中");
Thread.sleep(1000L);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}).start();
//3秒之后,将状态标志改为false,代表不继续运行
Thread.sleep(3000L);
flag=false;
System.out.println("程序运行结束");
}
}
参考内容:以上的内容来自个人总结于网易云课堂的学习。
总结:
线程的学习坑点有很多,大家一定要有耐心,因为想迈入高级java编程,多线程开发是无法避免的。我是阿达,一名喜欢分享知识的程序员,时不时的也会荒腔走板的聊一聊电影、电视剧、音乐、漫画,这里已经有172位小伙伴在等你们啦,感兴趣的就赶紧来点击关注我把,哪里有不明白或有不同观点的地方欢迎留言。