Java基础之多线程没那么复杂!
多线程的引入
1.什么是多线程
线程是程序执行的一条路径,一个进程中可以包含多条线程;多线程并发执行可以提高程序的效率
</br>
2.进程和线程之间的关系操作系统可以同时执行多个任务,每个任务就是进程;进程可以同时执行多个任务,每个任务就是线程。
<br>
3.多线程的应用场景红蜘蛛同时共享屏幕给多个电脑
迅雷开启多条线程一起下载
QQ开启多人聊天
服务器同时处理多个客户的请求
<br>
多线程并行和并发的区别
- 并行性和并发性是两个概念,并行性指在同一时刻,有多条指令在多个处理器上同时执行<br>
- 并发性指的是同一时刻只有一条指令被执行,但多个进程指令被快速切换执行是的在宏观上具有多个进程被同时执行的效果
<br>
Java程序运行原理和JVM的启动是多线程的吗?- java程序运行原理
- Java命令启动jvm,启动jvm等于启动一个应用程序,也就是启动了一个进程,该进程会自动启动一个“主线程”,然后主线程去调用某个类的main方法
- Jvm启动是多线程的的吗
- JVM启动至少启动了垃圾回收线程和主线程,所以是多线程
<br>
多线程的实现方式 1. 继承Thread类创建线程类(1) 定义Thread的子类,并重写该类的run方法,该ru的执行体就代表了线程需要完成的任务,因此run()方法被称为线程执行体
(2) 创建Thread子类的实例,即创建了线程对象<br>
(3) 调用线程对象的start()方法启动该线程
package Demo;
public class Demo1__Thread {
public static void main(String[] args) {
ChThread t=new ChThread();
t.start();
for(int i=0;i<1000;i++) {
System.out.println("我是主方法!");
}
}
}
class ChThread extends Thread {
@Override
public void run() {
super.run();
for(int i=0;i<1000;i++) {
System.out.println("我是run方法");
}
}
}
上述代码的执行验证了多线程,如果上述程序的执行过程是多线程的话,会发现屏幕中的 ”我是主方法”和“我是run方法” 的字样是交替出现的,这说明了程序的的执行过程为并行执行Thread类的Start()方法启动run()方法的线程,和主方法中的执行同时进行。
<br>
2.实现Runnable接口创建线程类(1) 定义一个实现了Runnable接口的实现类<br>
(2) 创建Runnable实现类的实例<br>
(3) 将创建的实例作为Thread类的target类创建Thread对象,该对象才是真正的线程对象 <br>
(4) 用创建的Thread对象启动线程
package xianchenhg;
public class Thread_Running implements Runnable {
private int i;
public void run() {
for(;i<100;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args) {
for(int i=0;i<100;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20) {
new Thread(new Thread_Running(),"线程1").start();
new Thread(new Thread_Running(),"线程2").start();
}
}
}
}
查看API文档,会发现Runnable接口只定义了run()方法这一个抽象类,所以实现Runnable接口的实现类只有run()方法,仅作为线程执行体,所以,Runnable对象仅仅作为Thread对象的target,而实际的线程对象依然是Thread实例,Thread实例负责执行target的run()方法。
3.实现Callable接口和Future接口创建多线程
(1)Callable接口更像是Runnable接口的增强版,相比较Runable接口,Call()方法新增捕获和抛出异常的功能;Call()方法可以返回值<br>
(2)Future接口提供了一个实现类FutureTask实现类,FutureTaks类用来保存Call()方法的返回值,并作为Thread类的target。<br>
(3)调用FutureTask的get()方法来获取返回值
package Demo;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* (1)创建Callable接口的实现类,并重写call()方法,该call()方法作为线程的执行体,且有返回值
* (2)创建了Callable接口的实现类的实例,并用FutureTask()方法包装对象,该FutureTask()对象实现了
* 将对象的返回值包装的功能
* (3)使用FutureTask对象将Thread对象的target,创建并启动线程
* (4)调用FutureTask对象的get()方法获得子线程执行结束后的返回值
* */
public class Callable_Future implements Callable<Integer> {
@Override
public Integer call() throws Exception { //重写Callable接口中的call()方法
int i=0;
for(;i<100;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
return i;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
//创建Callable的对象
Callable_Future ca=new Callable_Future();
FutureTask<Integer> ft=new FutureTask<Integer>(ca);
for(int i=0;i<100;i++) {
//返回值主线程的名称和执行代号
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20) {
new Thread(ft,"Callable线程").start();
//该方法将导致主线程被阻塞,直到call()方法结束并返回为止
//System.out.println("子线程的返回值"+ft.get());
}
}
try{
System.out.println("子线程的返回值"+ft.get());
}catch (Exception e) {
e