在Java中,main()方法是Java应用程序的入口方法。程序从main方法开始执行,依次向下执行每行代码,如果程序执行到某行代码时遇到阻塞,则程序将会停滞在该处。这就是一个单线程的程序。
由于单线程的功能十分有限,所以Java语言提供了非常优秀的多线程支持,程序可以通过简单的方式来启动多线程。
一、线程与进程
程序运行时,会生成一个进程,同时自动创建一个线程,该线程通常称为主线程(主线程的线程执行体不是run()方法确定的,而是main()方法确定的)。
进程——一个运行中程序,即当一个程序进入内存运行就变成了一个进程。它是系统分配资源的最小单位。
线程——即每一条顺序执行流。线程是进程的执行单元,是CPU调度的最小单位。
我们可以打开“任务管理器”>“性能”查看自己电脑的CPU下进程和线程的运行情况:
<img src="https://i-blog.csdnimg.cn/blog_migrate/0b928a88a35530256d81c57b895c66d2.png" data-rawwidth="1000" data-rawheight="890" class="origin_image zh-lightbox-thumb" width="1000" data-original="https://pic3.zhimg.com/v2-af8f17bcfea749e1eea8bb8627e0ce3e_r.png">
二、单线程和多线程
单线程的程序:即只有一条顺序执行流。
多线程的程序:包括多条顺序执行流,多个顺序流之间互不干扰、相互独立。
形象理解:
单线程的程序如同只有一个厨师的餐厅,他必须先烧汤后炒菜……而多线程的程序如同有多个厨师的酒店,他们有各自分工,相互独立。
三、线程的创建和启动
Java使用Thread类代表线程,所有线程对象都必须是Thread类或其子类的实例。
1.继承Thread类创建线程类
(1)实现步骤:
①定义Thread类的子类,并重写run方法(run方法的方法体表示需要线程完成的任务,故run方法又称线程执行体);
②创建Thread子类的实例;
③用线程对象的start方法启动线程。
分析run方法源码
/**
* If this thread was constructed using a separate
* 如果这个线程是独立使用的
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* Runnable类对象的run方法被调用
* otherwise, this method does nothing and returns.
* 否则,此方法不执行任何操作,返回。
* <p>
* Subclasses of <code>Thread</code> should override this method.
* Thread类的子类应该重写此方法
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
//若目标不为空
target.run();
}
}
(2)示例代码:
//第一步,定义Thread类的子类
public class DrawThread extends Thread{
//重写run方法
public void run(){
//线程执行体
……
}
public stactic void main(String [] args){
//第二步,创建Thread子类的实例
DrawThread drawThread=new DrawThread();
//第三步,用线程对象的start方法启动线程
drawThread.start();
}
}
(3)优缺点:
优势——
直接使用this即可访问当前线程;
劣势——
该线程类已经继承了Thread类,故不能再继承其他父类。
2.实现Runnable接口创建线程类(推荐)
(1)实现步骤:
①定义Runnable接口的实现类,并重写该接口的run方法;
②创建Runnable实现类的实例,并以该实例作为Thread的target来创建Thread对象,即线程对象;
③调用线程对象的start方法启动线程。
分析run方法的源码
/**
* When an object implementing interface <code>Runnable</code> is used
* 当一个实现了Runnable接口的对象被用于
* to create a thread, starting the thread causes the object's
* 去创建一个线程,启动线程导致对象的
* <code>run</code> method to be called in that separately executing
* run方法将被调在单独执行线程中
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* run方法的一般契约是它可以的
* take any action whatsoever.
* 采取任何行动。
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
(2)示例代码:
//第一步,定义Runnable接口的实现类
public class LoopThread implements Runnable{
//重写该接口的run方法
public void run() {
//线程执行体
……
}
public stactic void main(String [] args){
//第二步,创建创建Runnable实现类的实例
LoopThread loopThread=new LoopThread();
//第三步,通过new Thread(target,name)方法创建新线程
new Thread(loopThread,"循环线程").start();
}
}
(3)优缺点:
优势——
①线程类只实现了Runnable接口,还可以继承其他类;
②可以做到多个线程共享一个target对象;
劣势——
必须使用Thread.currentThread()方法才能访问到当前线程。