Поймите различия и взаимосвязи между процессами, потоками, сопрограммами, волокнами и виртуальными потоками в одной статье.
Поймите различия и взаимосвязи между процессами, потоками, сопрограммами, волокнами и виртуальными потоками в одной статье.

введение

В многопоточном программировании и параллельной обработке мы часто слышим понятия процессов, потоков, сопрограмм, волокон и виртуальных потоков. Хотя они оба связаны с параллельным программированием, многие люди не понимают их различий и взаимосвязей. В этой статье будет представлен углубленный анализ различий и взаимосвязей между процессами, потоками, сопрограммами, волокнами и виртуальными потоками, чтобы помочь читателям лучше понять различные концепции параллельного программирования.

1. Процесс

Процесс — это экземпляр программы, работающей на компьютере. Каждый процесс имеет собственное независимое пространство памяти и системные ресурсы и может иметь несколько потоков. Процессы независимы друг от друга. Они не могут обмениваться данными напрямую и должны обмениваться данными посредством межпроцессного взаимодействия (IPC).

Вот простой пример кода Java, показывающий, как создать процесс:

Язык кода:java
копировать
public class ProcessDemo {
    public static void main(String[] args) {
        ProcessBuilder processBuilder = new ProcessBuilder("myProgram.exe");
        try {
            Process process = processBuilder.start();
            // Дождитесь завершения выполнения процесса
            int exitCode = process.waitFor();
            System.out.println("Выполнение процесса завершено, код выхода:" + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

В приведенном выше коде,мы используемJavaизProcessBuilderкласс создает процесс,и выполнил вызов под названиемmyProgram.exeпрограмма。

2. Нить

Потоки относятся к независимым путям выполнения, выполняемым внутри процесса. Процесс может содержать несколько потоков, каждый поток выполняется независимо и имеет свой собственный порядок выполнения и статус.

К особенностям нитей относятся:

  1. Легкий: по сравнению с процессами,нить — более легкая исполнительная единица. Создание и уничтожение нить обходится дешевле,За короткое время можно создать большое количество нить.
  2. Общие ресурсы: нить разделяет пространство памяти и системные ресурсы процесса в пределах одного процесса. Это означает, что несколько пользователей могут напрямую получать доступ к одним и тем же данным и изменять их, что упрощает обмен данными и обмен данными.
  3. одновременное выполнение: несколько нить могут выполняться одновременно,Выполняйте задачи одновременно. Кванты процессорного времени могут быть распределены между разными местоположениями в соответствии с конкретным алгоритмом планирования.,Таким образом достигается одновременная обработка.
  4. Переключение контекста: поскольку нить выполняется одновременно,Операционная система требует переключения контекста между разными нитями. Переключение контекста означает сохранение состояния выполнения нити.,И восстановить статус выполнения еще одного нит,Этот процесс потребует определенных накладных расходов.
  5. Синхронизация нить: когда несколько нить получают доступ к общим ресурсам, могут возникнуть условия гонки и несогласованность данных. Чтобы обеспечить согласованность и правильность данных,Необходимо использовать механизм синхронизации,например блокировка мьютекса、Сумма сигнала、переменные состояния и т. д.
  6. Параллелизм возможен: на многоядерных процессорах,Несколько нить могут выполняться параллельно,Повышение эффективности выполнения программы. Параллельное выполнение через нит,Задачи можно разделить на несколько подзадач и обрабатывать одновременно.,Ускорить выполнение задач.

Подводя итог, можно сказать, что поток — это облегченная исполнительная единица, которая может выполняться одновременно и совместно использовать ресурсы процесса. Рационально используя потоки, мы можем полностью использовать вычислительную мощность компьютера и повысить эффективность выполнения и скорость ответа программы.

Поток — это исполнительная единица внутри процесса и базовая единица планирования ЦП. Каждый поток выполняется в контексте процесса и совместно использует пространство памяти и системные ресурсы процесса. Данные могут передаваться напрямую между потоками, поэтому взаимодействие между потоками становится более эффективным.

Создание и уничтожение потоков

2. Создание тем

Создание потоков в Java может быть достигнуто двумя способами: наследованием класса Thread и реализацией интерфейса Runnable. Далее мы представим эти два метода один за другим.

2.1 Наследование класса Thread

Во-первых, давайте посмотрим, как создать поток, унаследовав класс Thread. Конкретные шаги заключаются в следующем:

  1. Создать новый класс,Унаследовано от класса Thread,и переписатьrun()метод。run()методвключен в Логика выполнения нити。
Язык кода:java
копировать
public class MyThread extends Thread {
    @Override
    public void run() {
        // Логика выполнения нити
    }
}
  1. Создайте экземпляр этого класса и вызовите метод start(), чтобы запустить его.
Язык кода:java
копировать
MyThread myThread = new MyThread();
myThread.start();

Таким образом, мы можем создать новый поток и определить в нем логику выполнения потока.

2.2 Реализация Runnable-интерфейса

Помимо наследования класса Thread, мы также можем создавать потоки, реализуя интерфейс Runnable. Конкретные шаги заключаются в следующем:

  1. Создайте класс, реализующий интерфейс Runnable и метод run().
Язык кода:java
копировать
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // Логика выполнения нити
    }
}
  1. Создайте экземпляр этого класса и передайте его в качестве параметра конструктору класса Thread.
Язык кода:java
копировать
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();

Реализуя интерфейс Runnable, мы можем изолировать логику выполнения потока и улучшить возможность повторного использования и масштабируемость кода.

3. Разрушение нити

Уничтожение потока относится к процессу прекращения выполнения потока и освобождения связанных ресурсов. Уничтожение потоков в Java обычно выполняется автоматически, но мы также можем активно уничтожать потоки некоторыми способами.

3.1 Автоматическое уничтожение потоков

Когда метод run() потока завершается или генерируется неперехваченное исключение, поток автоматически уничтожается. В этот момент статус потока изменится на ПРЕКРАЩЕНО.

Язык кода:java
копировать
Thread thread = new Thread(() -> {
    // Логика выполнения нити
});
thread.start();

// Дождитесь окончания выполнения
thread.join();

// Определить, был ли уничтожен нить
if (thread.getState() == Thread.State.TERMINATED) {
    System.out.println("Нить была уничтожена");
}

3.2 Активное уничтожение потоков

Иногда нам необходимо активно уничтожать потоки при определенных условиях. Java предоставляет некоторые методы для активного уничтожения потоков.

3.2.1 Использование флагов

Мы можем установить бит флага в логике выполнения потока и решить, продолжать ли выполнение, проверив бит флага. Когда бит флага ложный, поток активно выйдет из цикла, тем самым достигнув активного уничтожения потока.

Язык кода:java
копировать
public class MyThread implements Runnable {
    private volatile boolean isRunning = true;

    @Override
    public void run() {
        while (isRunning) {
            // Логика выполнения нити
        }
    }

    public void stopThread() {
        isRunning = false;
    }
}

MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();

// Активно уничтожать нить при определенных условиях
myThread.stopThread();

В приведенном выше примере мы добавили логический флаг isRunning в класс MyThread. В логике выполнения потока мы решаем, продолжать ли выполнение, проверяя этот бит флага. Когда нам нужно активно уничтожить поток, мы вызываем метод stopThread(), чтобы установить для isRunning значение false, чтобы поток вышел из цикла.

3.2.2 Использование метода прерывания()

Другой способ активного уничтожения потоков — использование метода прерывания(). Этот метод прерывает выполнение потока и генерирует InterruptedException.

Язык кода:java
копировать
public class MyThread implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            // Логика выполнения нити
        }
    }
}

MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();

// Активно уничтожать нить при определенных условиях
thread.interrupt();

В приведенном выше примере мы использовали Thread.currentThread().isInterrupted() в логике выполнения потока, чтобы проверить, был ли поток прерван. Когда мы вызываем метод thread.interrupt(), метод isInterrupted() потока вернет true, заставляя поток выйти из цикла.

Планирование и синхронизация процессов и потоков

Прежде чем мы начнем, давайте рассмотрим основные понятия процессов и потоков. Процесс относится к экземпляру запущенной программы и имеет независимое пространство памяти и ресурсы. Поток — это исполнительная единица внутри процесса. Процесс может содержать несколько потоков, которые совместно используют пространство памяти и ресурсы процесса. В Java процессами управляет JVM, а потоки планируются операционной системой.

2. Планирование процессов и потоков

2.1 Планирование процессов

В операционной системе планирование процессов означает, что операционная система выбирает процесс из очереди готовности для распределения ресурсов ЦП в соответствии с определенной стратегией. За планирование процессов в Java отвечает операционная система, и мы не можем напрямую контролировать планирование процессов. Операционная система определяет, какой процесс получает время выполнения ЦП, на основе таких факторов, как приоритет процесса и алгоритм планирования.

2.2 Планирование потоков

Планирование потоков означает, что операционная система выбирает поток из очереди готовности для распределения ресурсов ЦП в соответствии с определенной стратегией. Java предоставляет некоторые механизмы, влияющие на планирование потоков.

2.2.1 Приоритет потока

У каждого нить есть приоритет,Используется для определения порядка выполнения при конкуренции за ресурсы ЦП. приоритет нить в Java варьируется от 1 до 10,По умолчанию5。Можно использоватьThread.setPriority()методнастраиватьнитьизприоритет。

Язык кода:java
копировать
Thread thread1 = new Thread(() -> {
    // Логика выполнения нить1
});
Thread thread2 = new Thread(() -> {
    // Логика выполнения нит2
});

thread1.setPriority(Thread.MAX_PRIORITY); // Установите приоритет нить1 на самый высокий
thread2.setPriority(Thread.MIN_PRIORITY); // Установите приоритет нить2 на самый низкий

thread1.start();
thread2.start();

Приоритет потока является лишь подсказкой и не гарантирует выполнение в порядке приоритета. Конкретное планирование потоков определяется операционной системой.

2.2.2 Сон потока

ПозвонивThread.sleep()метод,Можем перевести текущий нит в спящий режим,Сделайте паузу на некоторое время, прежде чем возобновить выполнение.

Язык кода:java
копировать
Thread thread = new Thread(() -> {
    // Логика выполнения нити
    try {
        Thread.sleep(1000); // Спать 1 секунду
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

Сон потока можно использовать для моделирования некоторых сценариев, требующих ожидания, или для настройки временного интервала выполнения потока.

3. Синхронизация процессов и потоков

В многопоточном программировании выполнение между потоками происходит одновременно, и могут возникнуть некоторые проблемы с синхронизацией, такие как состояния гонки и взаимоблокировки. Java предоставляет некоторые механизмы, которые помогут нам решить эти проблемы.

3.1 Критический раздел

критическая секция относится к фрагменту программы, области, которая может вызвать состояние гонки, когда несколько человек одновременно обращаются к фрагменту. Чтобы гарантировать критическое секцияиз Взаимоисключающий доступ,нас Можно использоватьsynchronizedКлючевые слова Приходить Изменитьметодиликодкусок。

Язык кода:java
копировать
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }
}

В приведенном выше примере,increment()иdecrement()метододеялоsynchronizedИзменить,Гарантированоcountпеременнаяиз Доступ является взаимоисключающимиз,Избегайте возникновения условий гонки.

3.2 Потоковая связь

нить Коммуникация подразумевает множествонитьмеждупроходитьобщийиз对象Приходить进行信息交换исинхронный。Javaпредоставилwait()notify()иnotifyAll()метод Приходить实现нитьмеждуизкоммуникация。

Язык кода:java
копировать
public class Message {
    private String content;
    private boolean isReady;

    public synchronized void setContent(String content) {
        while (isReady) {
            try {
                wait(); // Подождите, пока сообщение будет использовано
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.content = content;
        isReady = true;
        notifyAll(); // Сообщите, что другие сообщения готовы
    }

    public synchronized String getContent() {
        while (!isReady) {
            try {
                wait(); // Подождите, пока сообщение будет создано
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isReady = false;
        notifyAll(); // Уведомлять другие нить сообщения, которые были использованы
        return content;
    }
}

В приведенном выше примере,setContent()иgetContent()методиспользовалsynchronizedИзменить,обеспеченонитьмеждуизсинхронный。когда продюсернитьвызовsetContent()методчас,Если сообщение готово,Затем войдите в состояние ожидания, в противном случае установите содержимое сообщения и отметьте сообщение как готовое;,И оповестить других нить.потребительнитьвызовgetContent()методчас,Если сообщение еще не готово,Затем войдите в состояние ожидания; в противном случае получите содержимое сообщения и отметьте его как использованное;,И оповестить других нить.

Вот простой пример кода Java, показывающий, как создать и запустить поток:

Язык кода:java
копировать
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Нить Начать выполнение");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("выполнение завершено");
        });
        thread.start();
        System.out.println("Основная работа продолжает выполняться");
    }
}
Язык кода:java
копировать
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ComplexMultithreadingExample {
    public static void main(String[] args) {
        // Создайте пул нить, содержащий 5 нить
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // Создайте 10 задач и отправьте их в нить пул на выполнение.
        for (int i = 0; i < 10; i++) {
            Runnable task = new MyTask(i);
            executor.submit(task);
        }

        // Закрыть бассейн
        executor.shutdown();
    }
}

class MyTask implements Runnable {
    private int taskId;

    public MyTask(int taskId) {
        this.taskId = taskId;
    }

    @Override
    public void run() {
        System.out.println("Task " + taskId + " started.");

        try {
            // Время выполнения задачи моделирования
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Task " + taskId + " completed.");
    }
}

В приведенном выше коде мы создаем поток и выполняем в нем некоторые задачи. Основной поток и дочерние потоки могут выполняться одновременно, и порядок выполнения между ними не определен.

3. Сопрограмма

Сопрограмма — это более легкий поток, который может переключаться между различными точками выполнения, а не полагаться на планирование потоков операционной системы. Переключение сопрограмм явно контролируется программистом и может переключаться при необходимости для повышения производительности параллелизма.

Вот простой пример кода Python, показывающий, как использовать сопрограммы:

Язык кода:python
кодКоличество запусков:0
копировать
import asyncio

async def myCoroutine():
    print("Сопрограмма начинает выполняться")
    await asyncio.sleep(1)
    print("Выполнение сопрограммы завершено")

asyncio.run(myCoroutine())

В приведенном выше коде,мы используемPythonизasyncioБиблиотека создает сопрограмму,и выполнил некоторые задачи в сопрограмме。проходитьawaitКлючевые слова,Мы можем приостановить выполнение сопрограммы,Прежде чем продолжить, дождитесь завершения операции.

4. Волокно

Fiber — это облегченный поток в пользовательском режиме. Он запланирован самой пользовательской программой и не зависит от планирования потоков операционной системы. Волокна могут переключать выполнение внутри одного потока, что снижает стоимость переключения потоков и повышает эффективность параллельной обработки.

Вот простой пример кода C++, показывающий, как использовать волокна:

Язык кода:cpp
копировать
#includesys/ucontext.h>

ucontext_t context[2];

void fiber1() {
    printf("Fiber 1 начинает выполнение\n");
    swapcontext(&context[1], &context[0]);
    printf("Fibre 1 продолжает выполняться\n");
    swapcontext(&context[1], &context[0]);
    printf("Выполнение волокна 1 завершено\n");
}

void fiber2() {
    printf("Fiber 2 начинает выполнение\n");
    swapcontext(&context[0], &context[1]);
    printf("Fiber 2 продолжает выполняться\n");
    swapcontext(&context[0], &context[1]);
    printf("Выполнение волокна 2 завершено\n");
}

int main() {
    char stack1[8192];
    char stack2[8192];

    getcontext(&context[0]);
    context[0].uc_stack.ss_sp = stack1;
    context[0].uc_stack.ss_size = sizeof(stack1);
    context[0].uc_link = &context[1];
    makecontext(&context[0], fiber1, 0);

    getcontext(&context[1]);
    context[1].uc_stack.ss_sp = stack2;
    context[1].uc_stack.ss_size = sizeof(stack2);
    context[1].uc_link = &context[0];
    makecontext(&context[1], fiber2, 0);

    printf("Начинается основное выполнение\n");
    swapcontext(&context[0], &context[1]);
    printf("Главная нить продолжает выполнение\n");
    swapcontext(&context[0], &context[1]);
    printf("Основное выполнение завершено\n");

    return 0;
}

В приведенном выше коде,мы используемC++изucontextБиблиотека создает два волокна,и переключаться между волокнами。проходитьswapcontextфункция,Мы можем вручную управлять переключением оптоволокна.

5. Virtual Threads

Virtual Threads — это новая модель параллелизма, представляющая собой облегченный поток, реализованный на уровне виртуальной машины Java. Виртуальные потоки могут создавать и планировать большое количество виртуальных потоков в одном потоке, избегая накладных расходов на переключение контекста, вызванных слишком большим количеством потоков в традиционной модели потоков.

Сценарии применения

Вот простой пример кода Java, показывающий, как использовать виртуальные потоки:

Язык кода:java
копировать
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class VirtualThreadDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newVirtualThreadExecutor();
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            executorService.execute(() -> {
                System.out.println("виртуальныйнить" + taskId + «Начать выполнение»);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("виртуальныйнить" + taskId + «Выполнение завершено»);
            });
        }
        executorService.shutdown();
    }
}

В приведенном выше коде,мы используемJavaизExecutorsкласс создаетVirtual Пул потоков Threads и создает в нем 10 виртуальных потоков для одновременного выполнения.

Как использовать виртуальные потоки в Java

1. Обзор виртуальных потоков

Виртуальные потоки — это новая функция, представленная в Java 17, которая представляет собой облегченную модель параллельного выполнения. По сравнению с традиционными потоками виртуальные потоки имеют меньшие затраты памяти и более высокую производительность одновременного выполнения. Он обеспечивает одновременное выполнение за счет запуска нескольких виртуальных потоков в одном или нескольких физических потоках.

Основная концепция виртуальных потоков — это продолжение, контекст, в котором продолжается выполнение. Каждый виртуальный поток содержит продолжение, которое можно приостановить и возобновить. Когда виртуальный поток приостанавливается, его состояние сохраняется, не занимая ресурсы физического потока. Когда виртуальный поток возобновляется, он возобновляет выполнение с того места, где он был в последний раз приостановлен.

2. Используйте виртуальные потоки

Thread.setPriority(int) и Thread.setDaemon(boolean) неэффективны для виртуальных потоков.

Thread.getThreadGroup() вернет виртуальную пустую группу VirtualThreads.

Эффективность выполнения одной и той же задачи с использованием виртуальных потоков и потоков платформы совершенно одинакова, и повышения производительности не произойдет.

Попробуйте использовать управление параллелизмом в пакете JUC, например ReentrantLock, для управления синхронизацией вместо синхронизации. Синхронизированный блок кода закрепит (закрепит или заблокирует) виртуальный поток. Представитель JDK сказал, что это может быть оптимизировано позже.

Virtual Threads разработан как финальный класс и не может быть унаследован подклассами.

Не подходит для задач с интенсивными вычислениями. Виртуальные потоки подходят для задач с интенсивным вводом-выводом, но не для задач с интенсивными вычислениями, поскольку они выполняются в одном потоке и могут блокировать другие виртуальные потоки. Естественно, в новых функциях есть много ошибок, что действительно отражено в выпуске JDK. Используйте его с осторожностью! !

2.1 Подготовка среды

Прежде чем начать использовать виртуальные потоки, нам необходимо убедиться, что мы используем Java 17 и выше. Версию Java можно проверить с помощью следующего кода:

Язык кода:java
копировать
public class JavaVersionCheck {
    public static void main(String[] args) {
        String javaVersion = System.getProperty("java.version");
        System.out.println("Java Version: " + javaVersion);
    }
}

2.2 Создание виртуального потока

Использовать Виртуальный ThreadsНужно импортироватьjava.lang.VirtualThreadдобрый。нас Можетпроходитьнижекод СоздайтеVirtual Thread:

Язык кода:java
копировать
import java.lang.VirtualThread;

public class VirtualThreadDemo {
    public static void main(String[] args) {
        VirtualThread virtualThread = new VirtualThread(() -> {
            // Virtual Логика выполнения потока
        });
        
        virtualThread.start();
    }
}

В приведенном выше коде,наспроходитьVirtualThreadкласс создаетVirtual Thread и передается в лямбда-выражении как Virtual. Логика выполнения потока。Затемнасвызовstart()метод ЗапуститеVirtual Thread。

2.3 Пауза и возобновление виртуального потока

Virtual ThreadМожет ПозвонивVirtualThread.yield()метод Приходить主动сделайте паузуизосуществлять。после паузы,Virtual Состояние потока будет сохранено и будет ожидать следующего запланированного выполнения.

Язык кода:java
копировать
import java.lang.VirtualThread;

public class VirtualThreadDemo {
    public static void main(String[] args) {
        VirtualThread virtualThread = new VirtualThread(() -> {
            // Virtual Логика выполнения потока
            System.out.println("Virtual Thread: Hello, world!");
            VirtualThread.yield(); // Пауза Виртуальный Выполнение потока
            System.out.println("Virtual Thread: Goodbye!");
        });
        
        virtualThread.start();
    }
}

В приведенном выше коде Virtual Thread сначала печатает сообщение,ЗатемвызовVirtualThread.yield()методсделайте паузуизосуществлять。при следующей отправке,Virtual Поток продолжит выполнение с того места, где он в последний раз остановился, и напечатает еще одно сообщение.

2.4 Планирование виртуального потока

Планирование виртуальных потоков выполняется автоматически средой выполнения Java, и нам не нужно вмешиваться вручную. Среда выполнения Java запланирует несколько виртуальных потоков для одного или нескольких физических потоков для выполнения в соответствии с определенными стратегиями. Этот метод планирования может улучшить производительность параллелизма, одновременно сокращая накладные расходы на создание и уничтожение потоков.

3. Преимущества виртуальных потоков

По сравнению с традиционной потоковой моделью Virtual Threads имеет следующие преимущества:

3.1 Уменьшение затрат на память

В традиционной модели потоков каждому потоку необходимо выделить определенный лимит слов, и он не может продолжать выводить данные. Пожалуйста, используйте команду «продолжить», чтобы получить оставшиеся части.

Подвести итог

В этой статье мы даем углубленный анализ различий и взаимосвязей между процессами, потоками, сопрограммами, волокнами и виртуальными потоками. Процесс — это экземпляр программы, выполняющейся на компьютере, поток — это исполнительная единица внутри процесса, сопрограмма — это более легкий поток, волокно — это облегченный поток в пользовательском режиме, а виртуальные потоки — это облегченные потоки, реализованные в уровень виртуальной машины Java.

Понимая эти концепции, мы сможем лучше выбрать модель параллелизма, которая соответствует потребностям нашего проекта, и в полной мере воспользоваться преимуществами параллельного программирования.

Спасибо за чтение!

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose