Skip to content
Aleksandr Kuchuk edited this page Jun 20, 2016 · 14 revisions

Введение

Многопоточность. Ясно, что делать два дела одновременно и хорошо - это несомненный плюс. Вы можете ехать в метро и слушать музыку, чистить зубы и смотреть фильм. Мы живем в многопоточном мире:)

Зачем в Java?

  • Используем CPU, несколько ядер
  • многозадачность и производительность
  • асинхронная обработка событий

В чем же разница между процессом и потоком?

  • Процессы обладают собственным адресным пространством.
  • Потоки работают с общей памятью.
  • С потоками работает именно планировщик ОС.

Работа с потоками

Создание и запуск

Создать поток просто - мы должны отнаследоваться от Thread:

public class MyThread extends Thread {
@Override
public void run() {/*some work*/}
}

Запуск будет выглядеть как

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

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

Внимательный читатель сразу спросит, как так, а если я хочу, чтобы мой класс был потоком, но он уже наследует какой-то другой класс. Как быть?

Тут поможет второй вариант создания потока. Это разумеется реализация интерфейса! Наш интерфейс называется Runnable.

class Task implements Runnable {
@Override
public void run() {/*some work*/}
}

Запуск:

Thread thread = new Thread(new Task());
thread.start();

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

Thread thread = new Thread(new Runnable() {
@Override
public void run() {/*some work*/}
});

thread.start();

Есть еще третий вариант: это создать Timer.

Timer timer = new Timer();
timer.schedule(new TimeTask {
@Override
public void run() {/*some work*/}
}, 60);

Выполнение задачи в отдельном потоке, но по таймеру.

Теперь посмотрим что будет, если я вместо start() буду вызывать именно run() метод.

    void wrongRun() {
        ThreadExample te1 = new ThreadExample("My thread", 1);
        ThreadExample te2 = new ThreadExample("My thread 2", 2);
        te1.run();
        te2.run();
    }

И увидим мы то, что все будет выполняться последовательно, без многопоточности. Сначала отработает te1, а уже после него начнет работу te2. Поэтому НЕ вызывайте run() напрямую - это бесполезно.

Clone this wiki locally