什么是多线程
多线程是指在一个程序中同时运行多个线程(线程是指程序内的一个执行流),每个线程可以执行不同的任务。在多线程编程中,程序可以同时执行多个任务,而不是按照顺序逐个执行。多线程可以充分利用多核处理器的优势,提高程序的并发性和性能。
在多线程环境下,线程共享同一进程的内存空间,可以访问和修改共享的数据。线程之间可以进行通信和同步操作,通过线程间的消息传递和共享变量等机制,实现线程间的协作和数据交换。 多线程可以用于任务并行处理、提高程序的响应性和吞吐量,以及优化资源的利用等方面。然而,多线程编程也面临着线程安全、竞态条件等问题,需要仔细处理和管理共享数据的访问,以避免并发错误和数据不一致性的问题。
多线程的作用
在Java中,Stream(流)是一种用于处理集合数据的高级抽象概念。Java Stream API 提供了一种功能强大且表达力高的方式来处理数据集合,包括集合、数组等。使用Stream,可以更简洁、更具表达力地进行数据转换、过滤、映射、聚合等操作,同时还能利用多核处理器进行并行操作。以下是Java Stream 流的一些主要作用:
- 函数式风格的数据处理: 使用Stream,你可以以函数式风格处理数据,通过链式调用方法来进行各种数据操作。这使代码更易读、易于组合和重用。
- 数据转换和映射: Stream提供了
map操作,可以将一个元素映射为另一个元素,从而进行数据转换。例如,可以将一个集合中的每个元素映射为另一种类型的元素。 - 数据过滤: 使用
filter操作,可以根据特定条件筛选出符合条件的元素。这在从大型数据集中提取所需数据时非常有用。 - 数据聚合和归约: Stream提供了
reduce操作,可以对集合中的元素进行归约操作,例如计算总和、最大值、最小值等。 - 并行处理: Stream可以通过并行操作,在多核处理器上同时处理数据,从而提高处理速度。通过
parallelStream()方法,可以将Stream转换为并行流。 - 延迟执行: Stream中的操作通常是延迟执行的,即只有在终止操作(如
forEach、collect)被调用时,才会实际开始执行操作。这使得Stream可以对操作进行优化,例如只计算实际需要的数据。 - 流水线操作: Stream允许将多个操作连接成流水线,每个操作依次应用于流中的元素。这种方式使得代码结构清晰,易于理解。
- 简化代码: 使用Stream可以大大减少需要编写的中间临时变量和循环代码,使代码更加简洁。
线程其实是程序中的一条执行路径
线程创建方式1
1.定义一个子类继承Thread类,并重写run方法
2.创建Thread的子类对象
3.调用start方法启动线程(启动线程后,会自动执行run方法中的代码)
/**
*1. 继Thread类型,就是一个自定义的线程类
*/
public class MyThread extends Thread{
// 重号run 方法,写线程的执行任务
@Override
public void run() {
for (int i = 0; i <= 5; i++) {
System.out.println("子线程执行>"+i);
}
}
}
再定义一个测试类,在测试类中创建MyThread线程对象,并启动线程
public class ThreadTest1 {
//目标: 掌握线程的创建方式一:继承Thread类
// main方法是由一条默认的主线程负责执行。
public static void main(String[] args) {
// 3、创建MyThread线翟类的对象代表一个线翟
MyThread myThread = new MyThread();
// 4、start()方法: 启动线程(自动执行run方法的)
myThread.start();
for (int i = 0; i <= 5; i++) {
System.out.println("主线程执行>"+i);
}
}
}
线程创建方式2
1.先写一个Runnable接口的实现类,重写run方法(这里面就是线程要执行的代码)
2.再创建一个Runnable实现类的对象
3.创建一个Thread对象,把Runnable实现类的对象传递给Thread
4.调用Thread对象的start()方法启动线程(启动后会自动执行Runnable里面的run方法)
/**
* 定义一个任务类,实现Runnable接口
*/
public class MyRunnable implements Runnable{
//写子线程执行任务
@Override
public void run() {
for (int i = 0; i <= 5; i++) {
System.out.println("子线程MyRunnable执行>"+i);
}
}
}
/**
* 目标:掌握多线程创建二:实现Runnable接口
*/
public class ThreaTest {
public static void main(String[] args) {
//创建任务对象
MyRunnable myRunnable = new MyRunnable();
//把任务对象交给一个线程对象处理
Thread thread = new Thread(myRunnable);
thread.start();
for (int i = 0; i <= 5; i++) {
System.out.println("主线程ThreaTest执行>"+i);
}
}
}
线程创建方式2—匿名内部类
public class ThreadTest01 {
public static void main(String[] args) {
//掌握多线程创建方式二:匿名内部类写法
//匿名内部类写法
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <= 5; i++) {
System.out.println("子线程一执行>"+i);
}
}
}).start();
//lambda写法
new Thread(() -> {
for (int i = 0; i <= 5; i++) {
System.out.println("子线程二执行>"+i);
}
}).start();
for (int i = 0; i <= 5; i++) {
System.out.println("主线程执行>"+i);
}
}
}
线程的创建方式3
- 先定义一个Callable接口的实现类,重写call方法
- 创建Callable实现类的对象
- 创建FutureTask类的对象,将Callable对象传递给FutureTask
- 创建Thread对象,将Future对象传递给Thread
- 调用Thread的start()方法启动线程(启动后会自动执行call方法)等call()方法执行完之后,会自动将返回值结果封装到FutrueTask对象中
- 调用FutrueTask对的get()方法获取返回结果
import java.util.concurrent.Callable;
public class MyCollable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 描述线程的任务,返回线程执行返回后的结果。
// 需求:求1-n的和返回。
int sum=0;
for (int i = 1; i <= 100; i++) {
sum=sum+i;
}
return sum;
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 3、创建一个Callable的对象
MyCollable myCollable = new MyCollable();
// 4、把Callable的对象封装成一个FutureTask对象(任务对象)
// 未来任务对象的作用?
// 1、是一个任务对象,实现了Runnable对象.
// 2、可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果。
FutureTask<Integer> ift = new FutureTask<Integer>(myCollable);
// 5、把任务对象交给一个Thread对象
Thread thread = new Thread(ift);
thread.start();
// 6、获取线程执行完毕后返回的结果。
// 注意:如果执行到这儿,假如上面的线程还没有执行完毕
// 这里的代码会暂停,等待上面线程执行完毕后才会获取结果。
Integer integer = ift.get();
System.out.println("相加得到的值为:"+integer);
}
}
多线程多个线程测试
用 BigDecimal 写 累加和
import java.math.BigDecimal;
import java.util.concurrent.Callable;
public class BigDecimalTest implements Callable<BigDecimal> {
private int start;
private int end;
public BigDecimalTest(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public BigDecimal call() throws Exception {
BigDecimal sum = BigDecimal.valueOf(0);
for (int i = start; i <= end; i++) {
sum = sum.add(BigDecimal.valueOf(i));
}
return sum;
}
}
import java.math.BigDecimal;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test010 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// BigDecimalTest bd1 = new BigDecimalTest(1,200);
// FutureTask<BigDecimal> ift1 = new FutureTask<>(bd1);
// Thread thread = new Thread(ift1);
// thread.start();
//
// BigDecimalTest bd2 = new BigDecimalTest(201,400);
// FutureTask<BigDecimal> ift2 = new FutureTask<>(bd2);
// Thread thread2 = new Thread(ift2);
// thread2.start();
//
// BigDecimalTest bd3 = new BigDecimalTest(401,600);
// FutureTask<BigDecimal> ift3 = new FutureTask<>(bd3);
// Thread thread3 = new Thread(ift3);
// thread3.start();
//
// BigDecimalTest bd4 = new BigDecimalTest(601,800);
// FutureTask<BigDecimal> ift4 = new FutureTask<>(bd4);
// Thread thread4 = new Thread(ift4);
// thread4.start();
//
// BigDecimalTest bd5 = new BigDecimalTest(801,1000);
// FutureTask<BigDecimal> ift5 = new FutureTask<>(bd5);
// Thread thread5 = new Thread(ift5);
// thread5.start();
//
// BigDecimal sum1 = ift1.get();
// BigDecimal sum2 = ift2.get();
// BigDecimal sum3 = ift3.get();
// BigDecimal sum4 = ift4.get();
// BigDecimal sum5 = ift5.get();
// System.out.println("累加和为:"+(sum1.add(sum2).add(sum3).add(sum4).add(sum5).toString()));
BigDecimal sum1 = processSum(1, 200000);
BigDecimal sum2 = processSum(200001, 400000);
BigDecimal sum3 = processSum(400001, 600000);
BigDecimal sum4 = processSum(600001, 800000);
BigDecimal sum5 = processSum(800001, 1000000);
String s = sum1.add(sum2).add(sum3).add(sum4).add(sum5).toString();
System.out.println("程序运行结果为:" + s);
}
public static BigDecimal processSum(int start, int end) throws ExecutionException, InterruptedException {
BigDecimalTest bd = new BigDecimalTest(start, end);
FutureTask<BigDecimal> ift = new FutureTask<>(bd);
Thread thread = new Thread(ift);
thread.start();
return ift.get();
}
}