← Назад к вопросам

Что такое однопоточность?

1.2 Junior🔥 251 комментариев
#Dart#Асинхронность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое однопоточность

Однопоточность (single-threaded) — это модель выполнения, при которой приложение выполняет только один процесс за раз в главном потоке. Dart и Flutter используют однопоточную модель с асинхронным программированием.

Основные концепции

Однопоточность означает:

  • В один момент времени выполняется только одна операция
  • Нет конкурентного доступа к переменным
  • Нет race conditions
  • Нет deadlocks
  • Но есть заблокирование UI при долгих операциях
void main() {
  // Dart выполняет код последовательно
  print("1"); // выполнится первым
  print("2"); // выполнится вторым
  print("3"); // выполнится третьим
  
  // Результат: 1, 2, 3
}

Как это работает в Dart

Event Loop (Цикл событий):

// Dart использует Event Loop для управления асинхронностью

void main() {
  print("Start");
  
  // Микротаски (микротаски очередь)
  Future.microtask(() => print("Microtask"));
  
  // Обычные асинхронные операции (макротаски очередь)
  Future.delayed(Duration.zero, () => print("Future"));
  
  print("End");
}

// Результат:
// Start
// End
// Microtask
// Future

Event Loop в деталях

// 1. Выполни синхронный код (главный поток)
void main() {
  print("A");              // 1. Выполнится сразу
  
  // 2. Добавить в микротаски
  Future.microtask(() => print("B"));
  
  // 3. Добавить в макротаски
  Future(() => print("C"));
  
  print("D");              // 2. Выполнится сразу
}

// Порядок выполнения:
// A                (синхронный код)
// D                (синхронный код)
// B                (микротаски)
// C                (макротаски)

Проблема: блокирование UI

// ❌ ПЛОХО: долгая операция блокирует UI
void main() {
  print("Start");
  
  // Долгая синхронная операция
  var sum = 0;
  for (int i = 0; i < 1000000000; i++) {
    sum += i;
  }
  
  print("End: $sum");
  // Весь UI заморожен во время цикла!
}

// ✅ ХОРОШО: использовать асинхронность
Future<void> main() async {
  print("Start");
  
  // Отдать управление Event Loop'у
  await Future.delayed(Duration.zero);
  
  var sum = 0;
  for (int i = 0; i < 1000000000; i++) {
    sum += i;
  }
  
  print("End: $sum");
  // UI остается отзывчивым
}

Flutter и однопоточность

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        // ❌ ПЛОХО: блокирует UI
        onPressed: () {
          // Долгая синхронная операция
          for (int i = 0; i < 1000000000; i++) {
            counter++;
          }
          setState(() {});
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

// ✅ ПРАВИЛЬНО: использовать async/await
class _MyAppState extends State<MyApp> {
  int counter = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          // Дать UI время отреагировать
          await Future.delayed(Duration.zero);
          
          // Теперь можем выполнить операцию
          counter++;
          setState(() {});
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

Асинхронные операции в однопоточной среде

// Future — обещание получить результат в будущем
Future<String> fetchData() async {
  // Имитация сетевого запроса
  await Future.delayed(Duration(seconds: 2));
  return "Data loaded";
}

Future<void> main() async {
  print("Start");
  
  // await ждет результата, но не блокирует другие операции
  var data = await fetchData();
  
  print("Result: $data");
}

Примеры однопоточности в Flutter

// Загрузка данных без блокирования UI
class UserList extends StatefulWidget {
  @override
  State<UserList> createState() => _UserListState();
}

class _UserListState extends State<UserList> {
  late Future<List<User>> futureUsers;
  
  @override
  void initState() {
    super.initState();
    futureUsers = fetchUsers(); // Запускается асинхронно
  }
  
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<User>>(
      future: futureUsers,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        }
        if (snapshot.hasError) {
          return Text("Error: ${snapshot.error}");
        }
        
        return ListView(
          children: snapshot.data!.map((user) => UserTile(user)).toList(),
        );
      },
    );
  }
}

Future<List<User>> fetchUsers() async {
  final response = await http.get(Uri.parse("https://api.example.com/users"));
  // ... парсинг
}

Isolates для параллельных вычислений

Когда однопоточности недостаточно, используют Isolates:

// Isolate — отдельный поток с собственным Event Loop'ом
import 'dart:isolate';

// Функция для выполнения в отдельном потоке
Future<int> computeSum(int limit) async {
  var sum = 0;
  for (int i = 0; i < limit; i++) {
    sum += i;
  }
  return sum;
}

Future<void> main() async {
  print("Start");
  
  // Запустить в отдельном Isolate
  final result = await Isolate.run(() => computeSum(1000000000));
  
  print("Sum: $result");
  // UI остается отзывчивым!
}

Сравнение с многопоточностью

Однопоточность (Dart/Flutter):

  • ✅ Нет race conditions
  • ✅ Нет deadlocks
  • ✅ Проще для понимания
  • ✅ Меньше bugs
  • ❌ Долгие операции блокируют UI
  • ❌ Не использует несколько ядер процессора

Многопоточность (Java/Kotlin):

  • ✅ Использует несколько ядер
  • ✅ Может использовать все ресурсы
  • ❌ Race conditions
  • ❌ Deadlocks
  • ❌ Сложнее для понимания
  • ❌ Больше bugs

Лучшие практики в однопоточном Dart

Делай:

  • ✅ Используй async/await для асинхронных операций
  • ✅ Используй FutureBuilder / StreamBuilder
  • ✅ Разбивай долгие операции на части
  • ✅ Используй Isolates для тяжелых вычислений
  • ✅ Дай Event Loop'у время работать

Избегай:

  • ❌ Долгих синхронных операций в main thread
  • ❌ Блокирующих циклов
  • ❌ Синхронных HTTP запросов
  • ❌ Тяжелых вычислений в UI потоке

Практический пример: правильная работа с async

Future<void> loadAndProcess() async {
  try {
    // 1. Загрузить данные
    final data = await fetchData();
    
    // 2. Обработать данные
    final processed = await processData(data);
    
    // 3. Обновить UI
    setState(() {
      myData = processed;
    });
  } catch (e) {
    print("Error: $e");
  }
}

// В UI
ElevatedButton(
  onPressed: loadAndProcess,
  child: Text("Load"),
)

Заключение

Однопоточность в Dart/Flutter — это не ограничение, а особенность дизайна, которая:

  • Упрощает разработку
  • Убирает целый класс ошибок
  • Позволяет написать более надежный код
  • Требует понимания асинхронного программирования

Для Flutter разработчика критично понимать Event Loop и как правильно использовать async/await для создания отзывчивых приложений.

Что такое однопоточность? | PrepBro