偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試官:什么是多線程中的上下文切換?

開(kāi)發(fā) 前端
線程池可以復(fù)用線程,避免頻繁創(chuàng)建和銷毀線程,從而減少上下文切換開(kāi)銷。線程池中的線程會(huì)被重新分配任務(wù),避免重復(fù)的上下文切換。

在多線程編程中,“上下文切換”指的是操作系統(tǒng)在不同線程之間切換執(zhí)行時(shí)保存和恢復(fù)線程狀態(tài)的過(guò)程。每個(gè)線程都包含一個(gè)“上下文”,即當(dāng)前執(zhí)行的狀態(tài)信息,包括寄存器的值、程序計(jì)數(shù)器(指令位置)、堆棧指針等。

步驟:

  1. 保存當(dāng)前線程的狀態(tài):當(dāng)一個(gè)線程被掛起時(shí),操作系統(tǒng)會(huì)將該線程的寄存器、程序計(jì)數(shù)器等狀態(tài)信息保存到內(nèi)存中,以便將來(lái)能夠恢復(fù)。
  2. 恢復(fù)新線程的狀態(tài):接下來(lái),操作系統(tǒng)加載即將運(yùn)行的線程的狀態(tài)信息,使得該線程能夠從中斷的位置繼續(xù)執(zhí)行。
  3. 切換到新線程執(zhí)行:完成狀態(tài)的保存和恢復(fù)后,CPU就會(huì)開(kāi)始執(zhí)行新線程的指令。

開(kāi)銷:

雖然上下文切換使得多個(gè)線程能夠共享CPU資源,但它并非完全沒(méi)有成本。保存和恢復(fù)狀態(tài)需要時(shí)間,頻繁的上下文切換會(huì)導(dǎo)致:

  • 性能下降:頻繁切換會(huì)占用大量的CPU時(shí)間,導(dǎo)致真正執(zhí)行任務(wù)的時(shí)間減少。
  • 緩存失效:每次切換線程時(shí),CPU緩存可能會(huì)被刷新,導(dǎo)致緩存效率降低,增加內(nèi)存訪問(wèn)延遲。

如何減少上下文切換策略?

  • 減少線程數(shù)量:

每個(gè)線程都需要上下文切換資源,線程越多,切換頻率越高。如果任務(wù)量不大,減少線程數(shù)量可以降低上下文切換的頻率。

import java.util.List;
import java.util.Arrays;

public class ReduceThreadsExample {
    public static void main(String[] args) {
        List<String> tasks = Arrays.asList("task1", "task2", "task3", /* ... */ "task100");
        int threadCount = 10;
        int taskPerThread = tasks.size() / threadCount;

        for (int i = 0; i < threadCount; i++) {
            final int start = i * taskPerThread;
            final int end = (i == threadCount - 1) ? tasks.size() : (i + 1) * taskPerThread;

            new Thread(() -> {
                for (int j = start; j < end; j++) {
                    System.out.println("Processing " + tasks.get(j));
                }
            }).start();
        }
    }
}
  • 使用多線程池:

線程池可以復(fù)用線程,避免頻繁創(chuàng)建和銷毀線程,從而減少上下文切換開(kāi)銷。線程池中的線程會(huì)被重新分配任務(wù),避免重復(fù)的上下文切換。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 100; i++) {
            int task = i;
            executor.submit(() -> System.out.println("Processing task " + task));
        }

        executor.shutdown();
    }
}
  • 增加任務(wù)的批處理:

盡量將多個(gè)小任務(wù)合并為一個(gè)批處理任務(wù),減少線程之間的切換。這樣可以在同一個(gè)線程中連續(xù)完成多個(gè)任務(wù),降低切換的頻率。

import java.util.List;
import java.util.Arrays;

public class BatchProcessingExample {
    public static void main(String[] args) {
        List<String> tasks = Arrays.asList("task1", "task2", "task3", /* ... */ "task100");
        int batchSize = 10;

        for (int i = 0; i < tasks.size(); i += batchSize) {
            final List<String> batch = tasks.subList(i, Math.min(i + batchSize, tasks.size()));

            new Thread(() -> {
                for (String task : batch) {
                    System.out.println("Processing " + task);
                }
            }).start();
        }
    }
}
  • 盡量減少鎖競(jìng)爭(zhēng):

當(dāng)多個(gè)線程競(jìng)爭(zhēng)同一個(gè)鎖時(shí),線程會(huì)頻繁等待和喚醒,導(dǎo)致頻繁的上下文切換??梢酝ㄟ^(guò)優(yōu)化鎖的使用,或者采用更細(xì)粒度的鎖來(lái)減少鎖的競(jìng)爭(zhēng)。例如,使用讀寫(xiě)鎖來(lái)避免多個(gè)讀取線程間的競(jìng)爭(zhēng)。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockCompetitionExample {
    private static int counter = 0;
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                increment();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Counter: " + counter);
    }

    private static void increment() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }
    }
}
  • 無(wú)鎖編程:

在適用的場(chǎng)景下,使用無(wú)鎖編程(如原子操作或CAS操作)來(lái)實(shí)現(xiàn)線程間的同步,避免因?yàn)殒i競(jìng)爭(zhēng)而產(chǎn)生的上下文切換。這通常適用于輕量級(jí)的并發(fā)操作。

import java.util.concurrent.atomic.AtomicInteger;

public class LockFreeExample {
    private static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) {
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.incrementAndGet();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Counter: " + counter.get());
    }
}
  • 使用協(xié)程替代多線程:

協(xié)程是一種輕量級(jí)的“線程”實(shí)現(xiàn),可以在一個(gè)線程中實(shí)現(xiàn)多任務(wù)的協(xié)作切換。由于協(xié)程的切換是由程序控制的,不需要操作系統(tǒng)參與,因此可以大幅減少上下文切換的開(kāi)銷。JDK21后支持協(xié)程。

public class VirtualThreadExample {
    public static void main(String[] args) {
        try (var executor = java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()) {
            for (int i = 0; i < 100; i++) {
                int taskNumber = i;
                executor.submit(() -> {
                    System.out.println("Processing task " + taskNumber + " in " + Thread.currentThread());
                    // 模擬一些I/O操作或其他阻塞任務(wù)
                    try {
                        Thread.sleep(1000);  // 模擬任務(wù)執(zhí)行時(shí)間
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    return taskNumber;
                });
            }
        }  // 自動(dòng)關(guān)閉 executor,確保所有虛擬線程完成執(zhí)行
    }
}

責(zé)任編輯:武曉燕 來(lái)源: 架構(gòu)殿堂
相關(guān)推薦

2022-04-24 15:37:26

LinuxCPU

2019-05-06 14:36:48

CPULinux寄存器

2022-09-26 23:36:33

Linux系統(tǒng)CPU

2022-04-25 11:27:34

LinuxCPU

2024-08-27 09:46:39

Go協(xié)程效率

2021-05-25 11:10:36

GitLinux

2020-09-28 08:44:17

Linux內(nèi)核

2022-09-05 08:02:10

上下文切換服務(wù)器

2024-03-19 09:15:12

服務(wù)器CPUI/O

2020-02-21 10:09:06

調(diào)度進(jìn)程線程

2025-03-18 08:14:05

2023-11-24 16:18:15

操作系統(tǒng)Linux

2017-05-11 14:00:02

Flask請(qǐng)求上下文應(yīng)用上下文

2023-12-20 14:35:37

Java虛擬線程

2025-05-12 00:00:15

2025-04-03 07:33:56

2021-09-07 10:44:33

Java 注解開(kāi)發(fā)

2025-04-08 00:22:00

C#異步編程

2022-10-28 16:24:33

Context上下文鴻蒙

2021-02-19 10:02:57

HTTPSJava安全
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)