我们都了解在命令窗口输入Java.exe命令会启动JVM,等于启动了一个应用程序。
开启JVM相当于开启一个线程,该线程会自动的启动一个"主线程",然后主线程去调用某个类的main()方法。所以main()方法运行在主线程。
- 那么大家是不是有这样一个疑问:JVM的启动是多线程的吗? 答案是肯定的,JVM的启动至少启动了主线程与垃圾回收线程,所以是多线程的。
1.多线程的实现方式
那么Java中是如何实现多线程的呢?
由于线程是依赖进程而存在的,所以我们应该先创建一个进程(JVM)出来。而进程是由操作系统创建的,所以我们应该去调用系统功能创建一个进程。但是Java是不能直接调用系统功能,但是Java能调用C/C++写好的程序来实现多线程。由C/C++去调用系统功能创建进程,由Java去调用这样的东西,然后提供一些类供我们使用,我们就可以实现多线程程序了。
1.1 多线程代码实现方法一:继承Thread类
通过继承Thread类实现多线程代码的步骤 |
---|
1.书写一个类继承Thread类 |
2.重写书写这个类中的run()方法 |
3.创建子进程的实例/对象 |
4.调用start()方法开启此线程 |
//1.创建一个类继承Thread类
public class MyThread extends Thread {
//2.重写此类中的run()方法
@Override
public void run() {
System.out.println("线程A已经开启了");
}
}
public class MyTest {
public static void main(String[] args) {
//3.创建子线程的实例对象
MyThread myThread = new MyThread();
//4.执行该对象中的start()方法开启此线程
myThread.start();//运行结果:线程A已经开启了
}
}
- 注意:我们启动线程使用的不是run()方法,而应该是start方法,使该线程开始执行。
- Java虚拟机调用该线程的run方法。在上面的代码中MyThread类是一个线程类(继承的是Thread类),run方法中封装应该是必须被线程执行的代码。
- run方法中的代码实现原则是:一般将比较耗时的代码放在run方法中。
1.2 多线程代码实现方法二:实现Runnable接口
通过实现Runnable接口来实现多线程代码 的步骤 |
---|
1.书写一个类实现Runnable接口 |
2.重写实现Runnable接口的类中的run()方法 |
3.创建实现接口的实例对象 |
4.创建一个Thread类的实例对象,将实现接口的对象传进去 |
5.调用start()方法进行执行 |
//1.创建一个类实现Runnable接口
public class MyRunnable implements Runnable{
//2.重写实现类中的run()方法
@Override
public void run() {
System.out.println("子线程开启了");
}
}
public class MyTest {
public static void main(String[] args) {
//3.创建实现接口的实例对象
MyRunnable myRunnable = new MyRunnable();
//4.创建一个Thread类的实例对象,将实现接口的对象传进去
Thread th = new Thread(myRunnable);
//5.调用start()方法进行执行
th.start();
}
}
- 注意:这种创建多线程的方式,如何获取线程名称以及如何给线程设置名称
此种方法给子线程设置名称的方法 |
---|
方法一:通过提供有参构造方法来进行设置线程名称 |
方法二:通过线程的setName()方法来设置线程的名称 |
public class MyRunnable implements Runnable{
private String name;
//设置线程名称的方式一:通过提供有参构造方法来进行设置线程名称
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(this.name+"线程开启了");
}
}
public class MyTest {
public static void main(String[] args){
MyRunnable myRunnable = new MyRunnable("线程B");
Thread th = new Thread(myRunnable);
th.start(); //执行结果:线程B线程开启了
}
}
public class MyRunnale implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开启了");
}
}
public class MyTest {
public static void main(String[] args) {
MyRunnale myRunnale = new MyRunnale();
Thread th = new Thread(myRunnale);
//设置线程名称的方式二:通过setName()方法设置线程名称
th.setName("线程B");
th.start(); //线程B线程开启了
}
}
- 实现Runnable接口创建多线程,这种方式扩展性强,实现一个接口的同时还可以再去继承其他类,可以避免由Java单继承带来的局限性。
1.3 多线程代码实现方法三:实现Callable接口
通过实现Callable接口来实现多线程的步骤 |
---|
1.创建一个类实现Callable 接口 |
2.创建一个FutureTask类将Callable接口的子类对象作为参数传进去 |
3.创建Thread类,将FutureTask对象作为参数传进去 |
4.开启线程 |
//1.创建一个类实现Callable接口
public class MyCallable implements Callable {
private String name;
//提供有参构造方法为线程设置名称
public MyCallable(String name) {
this.name = name;
this.name=name;
}
//2.重写call()方法
@Override
public Object call() throws Exception {
System.out.println(this.name+"开启了");
return name;
}
}
public class MyTest {
public static void main(String[] args) throws Exception {
//3.创建实现Callable接口的对象
MyCallable myCallable = new MyCallable("线程A");
//4.创建一个FutureTask类的对象将实现Callable接口的对象传进去
FutureTask futureTask = new FutureTask(myCallable);
//5.创建一个Thread类对象,将FutureTask类的对象传进去
Thread th = new Thread(futureTask);
//6.开启线程
th.start();
System.out.println("==================");
//获得返回值
Object call = myCallable.call();
System.out.println(call);
}
}
- 注意:1.实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
- 2.执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。FutureTask 是 Future 接口的实现类。
总结
希望大家看了这篇博客后对实现多线程的方式有所了解,如果大家喜欢的话,不要忘了关注加评论呦。