java多线程实现的常用两种方法

时间:2022-11-11 20:06:34

作为或即将成为一名Java工程师,在工作和面试中必然要与多线程打交道,那么Java中的多线程是什么呢?我们先来聊一聊操作系统中的进程和线程

1.进程和线程

进程和线程的区别

进程简单来说就是操作系统中的一个任务,可以说是程序的执行,比如说你的电脑正在运行QQ和微信,那么这两个任务就是两个进程。而线程呢,是进程中不可或缺的一部分,一个进程中包含1-n个线程。两者比较官方的区别就是:

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)

线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)

那么我们平时说的多进程和多线程的意思也很明显了,多进程就是指操作系统能同时运行多个任务(程序),多线程就是指在同一程序中有多个线程顺序在执行。

进程和线程的生命周期

进程和线程的声明周期都可以概括成这几个部分:创建、就绪、运行、阻塞、终止,那么它们的具体过程,因为篇幅比较大,我会在下一篇博客中具体介绍。


2.多线程的创建

在第1部分中我们简单知道了进程和线程的区别以及多线程的基本概念,那么接下来就是对多线程的实际应用了。那么在Java程序中如何实现多线程呢,Java提供了三种创建多线程的方法

继承Thread类

继承Thread类是一种很常见的创建方式,它的具体做法是,该类继承Thread类并重写run()方法,具体的实现还是上代码更直观:

package com.csu.multiThread;

public class MultiThreadExtendsThread extends Thread{
String name;
public MultiThreadExtendsThread(String name) {
this.name = name;
}

public void run() {
for(int i=0;i<5;i++) {
System.out.println(name+"运行:"+i);

}


}
public static void main(String[] args) {
MultiThreadExtendsThread thread1 = new MultiThreadExtendsThread("A");
MultiThreadExtendsThread thread2 = new MultiThreadExtendsThread("B");
thread1.start();
thread2.start();


}

}
运行结果:

A运行:0
A运行:1
A运行:2
A运行:3
A运行:4
B运行:0
B运行:1
B运行:2
B运行:3
B运行:4
整个程序中含有三个线程,thread1、thread2以及mian主线程,主线程在调用main方法的时候启动,thread1和thread2通过start()方法,但是这里需要注意的一点是,start()的方法并不是让线程运行,它只是让线程出于一种就绪状态,至于什么时候运行,只有操作系统才能决定,所以如果有心的同学会发现,如果把上面的程序,再运行几遍会发现运行的结果与我贴出来的结果不一致。


实现Runnable接口

此方法实现多线程需要实现Runnable接口,然后重写run()方法,代码如下:

package com.csu.multiThread;

public class MultiThreadImplRunnable implements Runnable{
String name;
public MultiThreadImplRunnable(String name) {
this.name = name;
}


@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println(name+"运行:"+i);
}
}


public static void main(String[] args) {
MultiThreadExtendsThread thread1 = new MultiThreadExtendsThread("A");
MultiThreadExtendsThread thread2 = new MultiThreadExtendsThread("B");
new Thread(thread1).start();
new Thread(thread2).start();

}
}

 
运行结果:

A运行:0
B运行:0
A运行:1
B运行:1
A运行:2
A运行:3
B运行:2
A运行:4
B运行:3
B运行:4
这种方式实现多线程,与第一种相似,实现接口然后重写run方法,但是在启动线程的时候有所区别

在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象(thread1和thread2都作为target传入),然后调用Thread对象的start()方法来运行多线程代码。实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的。


两种实现方法的区别

相比第一种方法,第二种方法拥有一些优势,具体体现如下:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制(如果该类要继承多个类,那么第一种方法就不适用了)

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类