Java基础 - 多线程

Posted 风过无痕521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础 - 多线程相关的知识,希望对你有一定的参考价值。

一、概念

进程与线程

进程是程序的一次动态执行过程,它需要经历从代码加载,代码执行到执行完毕的一个完整的过程,这个过程也是进程本身从产生,发展到最终消亡的过程。

多进程操作系统能同时达运行多个进程(程序),由于 CPU 具备分时机制,所以每个进程都能循环获得自己的CPU 时间片。

由于 CPU 执行速度非常快,使得所有程序好像是在同时运行一样。

多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的一个基本单位。

线程是比进程更小的执行单位,线程是进程的基础之上进行进一步的划分。

所谓多线程是指一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单元称为线程,这些线程可以同时存在,同时运行,一个进程可能包含多个同时执行的线程

 

进程是操作系统进行资源分配的基本单位,而线程是操作系统进行CPU调度的基本单位。 

 

二、线程的状态


要想实现多线程,必须在主线程中创建新的线程对象。任何线程一般具有5种状态,即创建就绪运行阻塞终止。下面分别介绍一下这几种状态:

创建状态

在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时它已经有了相应的内存空间和其他资源,但还处于不可运行状态。

新建一个线程对象可采用Thread 类的构造方法来实现,例如 “Thread thread=new Thread()”。

就绪状态

新建线程对象后,调用该线程的 start() 方法就可以启动线程。当线程启动时,线程进入就绪状态。此时,线程将进入线程队列排队,等待 CPU 服务,这表明它已经具备了运行条件。

运行状态

当就绪状态被调用并获得处理器资源时,线程就进入了运行状态。此时,自动调用该线程对象的 run() 方法。run() 方法定义该线程的操作和功能。

阻塞状态

一个正在执行的线程在某些特殊情况下,如被人为挂起或需要执行耗时的输入/输出操作,会让 CPU 暂时中止自己的执行,进入阻塞状态。

在可执行状态下,如果调用sleep(),suspend(),wait() 等方法,线程都将进入阻塞状态,发生阻塞时线程不能进入排队队列,只有当引起阻塞的原因被消除后,

线程才可以转入就绪状态。

死亡状态

线程调用 stop() 方法时或 run() 方法执行结束后,即处于死亡状态。处于死亡状态的线程不具有继续运行的能力。

在此提出一个问题,Java 程序每次运行至少启动几个线程?

回答:至少启动两个线程,每当使用 Java 命令执行一个类时,实际上都会启动一个 JVM,每一个JVM实际上就是在操作系统中启动一个线程,Java 本身具备了垃圾的收集机制。

所以在 Java 运行时至少会启动两个线程,一个是 main 线程,另外一个是垃圾收集线程。

 

三、线程的操作方法

start() :启动线程

join() :强制执行

在线程操作中,可以使用 join() 方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续执行。

sleep():休眠

在程序中允许一个线程进行暂时的休眠,直接使用 Thread.sleep() 即可实现休眠。

interrupt():中断

当一个线程运行时,另外一个线程可以直接通过interrupt()方法中断其运行状态。

 

run():运行

run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,

还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。

 

wait():

notify():

notifyAll():

 

四、后台线程

在 Java 程序中,只要前台有一个线程在运行,则整个 Java 进程都不会消失,所以此时可以设置一个后台线程,这样即使 Java 线程结束了,此后台线程依然会继续执行,

要想实现这样的操作,直接使用 setDaemon() 方法即可。 

 

五、线程优先级

在 Java 的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时,哪个线程的优先级高,哪个线程就有可能会先被执行。

线程将根据其优先级的大小来决定哪个线程会先运行,但是需要注意并非优先级越高就一定会先执行,哪个线程先执行将由 CPU 的调度决定。

 

六、同步和锁

 

七、线程实现方式

1、继承Thread 类

 

2、实现Runnable接口

相比Thread 更便于资源共享

3、Callable 和 Future

相比Thread 类,Runnable接口,有返回值。

实际上 Thread 类和 Runnable 接口之间在使用上也是有区别的,如果一个类继承 Thread类,则不适合于多个线程共享资源,而实现了 Runnable 接口,就可以方便的实现资源的共享。

 

特殊

ThreadLocal

Threadlocal而是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据。

 

 

参考资料:

Java多线程看这一篇就足够了(吐血超详细总结)

java多线程的wait、notify/notifyAll区别

ThreadLocal

 

以上是关于Java基础 - 多线程的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程基础

Java基础教程:多线程基础——线程的状态

java 基础学习:多线程04

多线程Java多线程学习笔记 | 多线程基础知识

3.8 java基础总结①多线程

JAVA多线程和并发基础面试问答