MultiProcessingExercise
package MultiProcessingExercise20240811;
public class MultiProcessingExercise1 {
public static void main(String[] args) {
// 多线程
// 多线程是在软件或者硬件上实现多个线程并发执行的技术
// 多线程的好处
// 具有多线程能力的计算机因硬件支持,所以说能够在同一时间同时执行多个线程(并行),显著提升性能
// 并发和并行
/* 并发:在同一时间,多个指令在单个CPU上交替执行(沟槽的高并发),这些指令在微观上(本质上)其实并非同时进行的,但因为
CPU快速切换任务,所以说在宏观上看上去是同时进行的 */
// 并行:在同一时间,多个指令在多个CPU上同时执行
// 并发可以在单个(核)CPU上完成,其依赖于任务快速切换
// 并行只能在多个(核)CPU上完成,其依赖于多个CPU同时工作
// 并发是通过快速切换任务来实现“同时”处理多个任务的效果,而并行是真正的同时处理多个任务
// 进程
// 简单而言,进程可以理解为正在运行的程序
// 独立性:进程是一个可以独立运行的基本单位,同时其也是系统分配资源和调度的独立单位
// 动态性:进程的实质是程序的一次执行过程,进程是动态产生、动态消亡的
// 并发性:任意进程都可以和其他进程一起并发执行
// 线程
// 线程是进程中的单个顺序控制流,是一条执行路径
// 单线程:一个进程若只有一条执行路径,那么称为单线程程序
// 多线程:一个进程若有多条执行路径,那么称为多线程程序
// 如:杀毒软件中有不同的功能,不同的功能可以同时运行,那么杀毒软件就是一个多线程程序,不同的功能就是不同的线程
// 多线程的实现方法
// 1.继承Thread(线,线程)类
// 定义一个类继承Thread类
// 在子类中重写run()方法(这个就是该线程的核心逻辑)
// 创建Thread子类的对象,并用start方法开启线程
// void start() 用于开启一条线程,开启之后,此线程开始执行,JVM虚拟机调用线程中的run方法
MyThread1 thread1 = new MyThread1();
MyThread1 thread2 = new MyThread1();
// 因为Thread中有set和get方法,所以说即使子类不写,也可以用对应的set和get方法
thread1.setName("线程1");
thread2.setName("线程2");
// 开启线程
thread1.start(); // 可以看见两条线程交替进行输出,分别在抢占CPU的资源
thread2.start();
// 注:若不用start方法开启线程,而是直接用对象调用run方法,就相当于普通的方法调用,而不是多线程
System.out.println(Runtime.getRuntime().availableProcessors());
// 用Runtime中的方法得到CPU可用的线程:20,并且发现主线程是先于thread1和thread2的
}
}
MyThread1
package MultiProcessingExercise20240811;
public class MyThread1 extends Thread{
// void run() 在线程开启之后,该方法被调用执行(该方法就是该线程的核心逻辑)
@Override
public void run() {
// 打印数字
for (int i = 0; i < 100; i++) {
System.out.println(this.getName() + ": " + i);
}
}
}
MultiProcessingExercise2
package MultiProcessingExercise20240811;
public class MultiProcessingExercise2 {
public static void main(String[] args) {
// 多线程的实现方法
// 2.实现Runnable接口
// 定义一个类实现Runnable接口
// 在实现类中重写run方法
// 创建实现类对象并将实现类对象作为Thread构造方法的参数
// Thread的构造方法
// Thread(Runnable target) 分配一个新的Thread对象
// Thread(Runnable target, String name) 分配一个新的Thread对象
// 创建Runnable实现类对象
MyThread2 runnable1 = new MyThread2();
MyThread2 runnable2 = new MyThread2();
// 为其取名
runnable1.setName("线程1");
runnable2.setName("线程2");
// 通过Thread的构造方法创建线程
Thread thread1 = new Thread(runnable1);
Thread thread2 = new Thread(runnable2);
// 用start方法开启线程
thread1.start();
thread2.start();
// 注:因为用Runnable实现类来创建线程没有继承Thread类,所以说不能直接使用set和get方法
// 但是可以使用Thread中的currentThread方法来得到线程,然后再调用set和get方法
}
}
MyThread2
package MultiProcessingExercise20240811;
public class MyThread2 implements Runnable{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println(this.getName() + ": " +i);
}
}
}
MultiProcessingExercise3
package MultiProcessingExercise20240811;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MultiProcessingExercise3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 多线程的实现方法
// 3.实现Callable接口
// 定义一个类实现Callable接口
// 在实现类中重写call()方法
// 创建实现类对象
// 创建Future的实现类FutureTask对象,将Callable实现类的对象作为构造方法的参数
// 创建Thread类对象,将FutureTask对象作为构造方法的参数,并启动线程
// 再调用FutureTask的get方法,可以得到线程结束之后的结果
MyThread3 callable1 = new MyThread3();
MyThread3 callable2 = new MyThread3();
FutureTask<Integer> ft1 = new FutureTask<>(callable1);
FutureTask<Integer> ft2 = new FutureTask<>(callable2);
Thread t1 = new Thread(ft1, "线程1");
Thread t2 = new Thread(ft2, "线程2");
t1.start();
t2.start();
System.out.println(ft1.get());
System.out.println(ft2.get());
}
}
MyThread3
package MultiProcessingExercise20240811;
import java.io.IOException;
import java.util.concurrent.Callable;
public class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws IOException {
int sum = 0;
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
sum += i;
}
return sum;
}
}