虚拟线程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; } }
|