Главный поток в Java

При запуске программы автоматически создается главный поток — поток, который выполняет метод main(), то есть главный метод программы. В рамках главного потока могут создаваться(запускаться) дочерние потоки(подпотоки), в которых, в свою очередь также могут запускаться потоки, и так далее. Главный поток от прочих потоков отличается тем, что создается первым.

Поток с точки зрения объектной модели Java — это объект класса, наследующего класс Thread или реализующего интерфейс Runnable. Поскольку это объект, то на него можно и нужно сделать ссылку. Ссылка записывается в объектную переменную. Однозначно эта объектная переменная может носиться к классу Thread.

У класса Thread есть статический метод currentThread(), которым в качестве результата возвращается ссылка на поток, из которого вызывался метод. Поэтому если метод вызывать в главном методе программы(инструкция вида Thread.currentThread()), получим ссылку на главный поток. Этим чудесным обстоятельством воспользуемся в примере, представленном в программе 1.1.

Программа 1.1:

public class ThreadDemo {
        // Главный метод может выбрасывать исключение: InterruptedException
	public static void main(String[] args) throws InterruptedException{
		// Объектная переменная для записи ссылки на главный поток:
		Thread t;
		// Время (в миллисекундах) задержки в выполнении потока:
		long time = 2500;
		// Получение ссылки на объект главного потока:
		t = Thread.currentThread();
		// Вывод сведений о потоке в консольное окно:
		System.out.println(t);
		// Изменение имени потока:
		t.setName("Это главный поток");
		// Считывание приоритета потока:
		int p = t.getPriority();
		// Изменение приоритета потока:
		t.setPriority(++p);
		// Вывод сведений о потоке в консольное окно:
		System.out.println(t);
		// Текстовое сообщение о приостановке выполнения потока:
		System.out.println("Выполнение потока приостановлено на " + (double)time/1000 + " секунд.");
		// Приостановка выполнения потока:
		Thread.sleep(time);
		// Завершение работы программы:
		System.out.println("Работа программы завершена!");

	}
}

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

Thread[main,5,main]
Thread[Это главный поток,6,main]
Выполнение потока приостановлено на 2.5 секунд.
Работа программы завершена!

Теперь рассмотрим и проанализируем программный код. Неприятности начинаются прямо с сигнатуры метода main(). При описании этого метода мы использовали инструкцию throws InterruptedException, которая означает, всего-навсего, что главный метод может выбрасывать необрабатываемое исключение класса InterruptedException(прерывание потока).

Необходимость в такой инструкции в сигнатуре метода вызвана тем, что в теле метода вызывается статический метод sleep() класса Thread.

Командой Thread t в теле метода объявляется объектная переменная, в которую затем запишем ссылку на главный поток программы(точнее, на объект главного потока). Время задержки в выполнении главного потока(в миллисекундах) записывается в переменную time.

Получение ссылки на объект главного потока выполняется командой t = Thread.currentThread(). После этого выводим информацию о главном потоке в консольное окно с помощью команды System.out.println(t), в которой аргументом методу println() передается ссылка на поток. Это возможно благодаря переопределенному в классе Thread методу toString().

В результате «вывода на экран» объекта потока появляется такое сообщение: ключевое слово Thread и затем в квадратных скобках три параметра: имя потока, его приоритет и имя группы потока. По умолчанию имя главного потока main, приоритет равен 5, а имя группы потока тоже main. То есть для главного потока сообщение будет иметь вид Thread[main,5,main].

Группы потоков — группы, в которые объединяются потоки для повышения уровня управляемости и степени безопасности. Некоторые действия можно выполнять сразу для всех потоков группы.

Командой t.setName(«Это главный поток») изменяется имя потока. Считывание приоритета потока выполняется инструкцией int p = t.getPriority(). Затем с помощью команды t.setPriority(++p) на единицу увеличивается значение приоритета процесса. Затем снова выполняется вывод свдений о потоке, для чего используем команду System.out.println(t).

После всех этих действий на некоторое время приостанавливаем выполнение главного потока(выполнение программы). Используем при этому команду Thread.sleep(time), предварительно выведя на экран текстовое сообщение о том, что поток будет приостановлен. Перед завершением работы программы выводим текстовое сообщение «Работа программы завершена!».

Статический метод sleep() вызывался через имя класса Thread. То же можно было сделать через объектную переменную t. Обращаем также внимание на то, что между выводом последнего и предпоследнего сообщений в консольном окне проходит определенное время(точнее, 2500 миллисекунд, или 2.5 секунды).