Java新特性-虚拟线程

虚拟线程VS线程

1.传统的线程模式中,线程相关的操作都高度依赖于操作系统

2.线程切换设计将当前正在执行的线程暂停,并切换到另一个线程进行执行。涉及保存当前线程的上下文信息(寄存器状态、堆栈指针等)然后加载下一个线程的上下文信息,这种切换过程需要大量的CPU时间和资源。

1
2
3
4
1.上下文开销,切换线程需要保存和恢复线程的上下信息,这些操作需要涉及内核态和用户态之间的切换,以及对内存的读写操作,这些都会耗费一定的CPU时间
2.缓存失效,当线程切换发生时,当前执行线程的缓存数据可能会失效。因为不同线程往往共享同一级缓存,当切换到新线程时,之前线程的缓存数据可能无法被新线程有效利用,需要重新加载数据,导致额为的延迟和资源消耗。
3.调度开销,线程切换是由草欸系统的调度器决定的,调度器需要评估和选择下一个要执行的线程。这个过程涉及调度算法的运算和决策,会占用一定的CPU时间和资源
4.竞争和时间同步机制,在多线程环境下,线程之间可能会发生竞争和冲突,需要使用同步机制来确保数据的一致性和互斥访问。线程切换会导致同步机制的开销,例如互斥锁的获取和释放

3.系统能够同时调度的线程是有限的

4.对于处理大量IO的任务,使用线程十分低效。例如读写文件、网络请求、读写数据库

使用方法

1.线程池方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.Random;
import java.util.concurrent.*;

public class ThreadPoolExample {
public static void main(String[] args) {
// 创建一个线程池,控制并发线程的数量
ExecutorService executorService = Executors.newFixedThreadPool(20);

// 提交任务给线程池处理
Future<Double> result = executorService.submit(new MemoryTask());

try {
long startTime = System.currentTimeMillis();
// 获取任务的执行结果,这里会阻塞直到任务完成
double value = result.get();
long endTime = System.currentTimeMillis();
System.out.println("Memory task result: " + value);
System.out.println("Time is:" + (endTime - startTime));
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 关闭线程池
executorService.shutdown();
}

static class MemoryTask implements Callable<Double> {
@Override
public Double call() throws Exception {
// 执行耗时的读写内存任务
return calculatePi(100000000);
}

private static double calculatePi(int numPoints) {
Random random = new Random();
int numPointsInsideCircle = 0;

for (int i = 0; i < numPoints; i++) {
double x = random.nextDouble();
double y = random.nextDouble();

// 判断点是否在圆内
if (x * x + y * y <= 1) {
numPointsInsideCircle++;
}
}

// 计算圆周率的估计值
return 4.0 * numPointsInsideCircle / numPoints;
}
}
}

2.虚拟线程方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.util.Random;
import java.util.concurrent.*;

public class ThreadVirtualPoolExample {
public static void main(String[] args) {
// 创建一个线程池,控制并发线程的数量
ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();

// 创建大量虚拟线程并调度:
ThreadFactory tf = Thread.ofVirtual().factory();

for (int i=0; i < 100000; i++) {
Thread vt = tf.newThread(() -> {
long startTime = System.currentTimeMillis();
double value = calculatePi(1000);
long endTime = System.currentTimeMillis();
System.out.println("Memory task result: " + value);
System.out.println("Time is:" + (endTime - startTime));
});
executorService.submit(vt);
}
}

private static double calculatePi(int numPoints) {
Random random = new Random();
int numPointsInsideCircle = 0;

for (int i = 0; i < numPoints; i++) {
double x = random.nextDouble();
double y = random.nextDouble();

// 判断点是否在圆内
if (x * x + y * y <= 1) {
numPointsInsideCircle++;
}
}

// 计算圆周率的估计值
return 4.0 * numPointsInsideCircle / numPoints;
}
}

Java新特性-虚拟线程
https://www.eldpepar.com/coding/37983/
作者
EldPepar
发布于
2023年10月6日
许可协议