Java MultiThreading (один)
Как очень важная точка знания в Java, все еще необходимо обобщить его здесь.
1. Жизненный цикл потока и пять основных состояний
Что касается жизненного цикла тем в Java, давайте сначала посмотрим на следующую классическую картинку:
Вышеуказанная фигура в основном охватывает важные знания о многопользовательском языке на Java. После того, как вы овладеете точками знаний на приведенной выше рисунке, вы в основном освоите многопоточное в Java. В основном, включая:
В темах Java есть пять основных состояний
Новое состояние (новое): когда создается пара объектов потока, оно входит в новое состояние, например: поток t = new Mythread ();
Готовное состояние (запустить): когда метод start () объекта потока (t.start ();), поток входит в состояние готового состояния. Поток в состоянии готовности просто означает, что поток готов и ждет, пока ЦП не запланирует выполнение в любое время, а не в том, что поток будет выполняться сразу после выполнения t.start ();
Государство. Примечание. Готовное состояние - единственная запись в управляемом состоянии, то есть, если поток хочет ввести в состояние выполнения для выполнения, оно должно сначала быть в состоянии готового состояния;
Заблокированное состояние: по какой -то причине поток в состоянии работающего, временно отказывается от использования ЦП и останавливает выполнение. В настоящее время он входит в состояние блокировки. У него не будет возможности снова вызвать процессор, чтобы войти в состояние бега. Согласно причинам блокировки, состояния блокировки можно разделить на три типа:
1. В ожидании блокировки: поток в состоянии работающего состояния выполняет метод wait (), чтобы поток вошел в ожидание состояния блокировки;
2. Синхронизированное блокирование- Поток не может получить синхронизированный блокировку синхронизации (поскольку блокировка занята другими потоками), он входит в синхронизированное состояние блокировки;
3. Другое блокировка-поток введет состояние блокировки, вызывая Sleep () или Join () потока или выпустив запрос ввода/вывода. Когда состояние Sleep () истекло, join () ждал, пока поток заканчивается или истекло, или обработка ввода-вывода была завершена, поток снова въехал в состояние готового состояния.
Мертвый: поток закончил выполнение или выходит из метода run () из -за исключения, а поток заканчивает свой жизненный цикл.
2. Создание и стартап многопоточных чтений Java
В Java есть три основные формы создания нити
1. Унаследовать класс потока и переопределить метод run () класса.
класс Mythread Extends Thread {private int i = 0; @Override public void run () {for (i = 0; i <100; i ++) {System.out.println (thread.currentThread (). GetName () + "" + i); }}} public Class Threadtest {public static void main (string [] args) {for (int i = 0; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); if (i == 30) {Thread mythread1 = new mythread (); // Создать новую ветку mythread1 Этот поток входит в новый поток состояния mythread2 = new mythread (); // Создать новую ветку MyThread2 Этот поток входит в новое состояние mythread1.start (); // Вызовите метод start (), чтобы поток введите в состояние готового состояния mythread2.start (); // Вызовите метод start (), чтобы поток введите состояние готового состояния}}}}Как показано выше, наследуя класс потоков, новый класс потока Mythread определяется перезапись метод run (), где тело метода метода run () представляет задачу, которую необходимо выполнить поток, и называется корпусом выполнения потока. При создании этого объекта класса потока создается новый поток и входит в новое состояние потока. Вызовая метод start (), на который ссылаются объект потока, поток входит в состояние готового состояния. В настоящее время поток может не выполняться немедленно, в зависимости от времени планирования процессора.
2. Реализуйте запускаемый интерфейс и переопределите метод run () интерфейса. Метод run () также является корпусом выполнения потока, создайте экземпляр класса выполнения реализации и используйте этот экземпляр в качестве цели класса потока для создания объекта потока. Объект потока является реальным объектом потока.
класс Myrunnable Refranse Runnable {private int i = 0; @Override public void run () {for (i = 0; i <100; i ++) {System.out.println (thread.currentThread (). GetName () + "" + i); }}} public Class Threadtest {public static void main (string [] args) {for (int i = 0; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); if (i == 30) {runnable myrunnable = new myrunnable (); // Создать объект из выполнения потока класса реализации Thread1 = новый поток (myrunnable); // Создать новый поток с Myrunnable в виде потока целевого потока потока 2 = новый поток (myrunnable); Thread1.start (); // Вызовите метод start (), чтобы поток введите в систему reade state nath2.start (); }}}} Я считаю, что все знакомы с вышеупомянутыми двумя способами создания новых тем. Так в чем же взаимосвязь между потоком и запусками? Давайте сначала посмотрим на следующий пример.
public Class Threadtest {public static void main (string [] args) {for (int i = 0; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); if (i == 30) {runnable myrunnable = new myrunnable (); Thread Think = new Mythread (Myrunnable); Thread.Start (); }}}} класс MyRunnable Reculments Runnable {private int i = 0; @Override public void run () {System.out.println ("в Myrunnable Run"); for (i = 0; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); }}} класс Mythread Extends Thread {private int i = 0; Public Mythread (Runnable Runnable) {Super (Runnable); } @Override public void run () {System.out.println ("в Mythread Run"); for (i = 0; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); }}}Точно так же то же самое относится и к созданию потоков, которые реализуют запускаемый интерфейс, разница в том, что
1 потока потока = новый Mythread (Myrunnable);
Так может ли этот метод успешно создать новый поток? Ответ да. Что касается тела выполнения потока в это время, то является ли метод run () в Myrunnable Interface или метод run () в классе Mythread? Через вывод мы знаем, что тело выполнения потока - это метод run () в классе Mythread. Фактически, причина очень проста, потому что сам класс потоков также реализует выполняемый интерфейс, а метод run () сначала определяется в запускаемом интерфейсе.
Public Interface Runnable {public Abstract void run (); } Давайте посмотрим на реализацию метода run () в интерфейсе запуска в классе потока:
@Override public void run () {if (target! = Null) {target.run (); }}То есть при выполнении метода run () в классе потока он сначала определит, существует ли цель. Если он существует, выполняется метод run () в цели, то есть метод run () в классе, который реализует запускаемый интерфейс и перезаписывает метод run (). Однако в приведенных выше столбцах, из -за существования полиморфизма, метод run () в классе потока вообще не выполняется, а тип времени выполнения, то есть метод run () в классе Mythread непосредственно выполняется.
3. Создайте потоки, используя Callable и будущие интерфейсы. В частности, он создает класс реализации для вызова интерфейса и реализует метод Clall (). И используйте класс FutureTask, чтобы обернуть объект Callable реализации, и используйте этот объект FutureTask в качестве цели объекта потока для создания потока.
Это кажется немного сложным, но будет ясно, если вы посмотрите напрямую на пример.
public Class Threadtest {public static void main (string [] args) {callable <Integer> mycallable = new MyCallable (); // Создать MyCallable Object futureTask <Integer> ft = new FutureTask <Integer> (MyCallable); // Использовать FutureTask, чтобы обернуть MyCallable объект для (int i = 0; i <100; i ++) {System.out.println (thread.currentThread (). GetName () + "" + i); if (i == 30) {Think Think = new Thread (ft); // объект FutureTask создает новый поток в качестве цели потока объекта потока. Start (); // Поток входит в состояние готового состояния}} system.out.println («Основной поток для цикла был выполнен ..»); try {int sum = ft.get (); // Получить результат, возвращаемый методом Call () в недавно созданной новой системе потоков.out.println ("sum =" + sum); } catch (прерванное искусство e) {e.printstacktrace (); } catch (executionException e) {e.printstackTrace (); }}} класс MyCallable реализует Callable <Integer> {private int i = 0; // В отличие от метода run (), метод Call () имеет возвратное значение @Override public integer call () {int sum = 0; for (; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); sum += i; } return sum; }}Во -первых, мы обнаружили, что при реализации метода Callable Interface метод run () больше не является методом run (), а метод Call (). Этот метод Call () является телом выполнения потока, а также имеет возвратное значение! При создании нового потока объект MyCallable завершается FutureTask, а также служит целью для объекта потока. Затем посмотрите на определение класса FutureTask:
открытый класс FutureTask <v> реализует RunnableFuture <v> {// ....} Public Interface RunnableFuture <v> Extends Runnable, Future <v> {void run (); }Поэтому мы обнаружили, что класс FutureTask фактически реализует как бегущие, так и будущие интерфейсы, что делает его двойные характеристики будущего и запуска. Через выполняемую функцию ее можно использовать в качестве цели объекта потока, и будущая функция позволяет получить возвращаемое значение метода Call () в недавно созданном потоке.
После выполнения этой программы мы обнаруживаем, что сумма = 4950 всегда является последним выводом. «Основной поток для петли был выполнен ...», вероятно, будет выходить в середине петли детского потока. Из механизма планирования потоков процессора мы знаем, что нет проблем с выходом вывода «Основной поток для цикла был выполнен ...», так почему Sum = 4950 будет выходить навсегда?
Причина заключается в том, что когда метод Call () дочернего потока () получается с помощью метода ft.get (), когда метод дочернего потока еще не выполнен, метод ft.get () будет блокироваться до тех пор, пока метод Call () не будет выполнен до получения возврата значения.
Вышеуказанное в основном объясняет три общих метода создания потока. Для запуска потоков все они называются методом start () объекта потока. Важно отметить, что метод start () не может быть вызван дважды на одном объекте потока.
Iii. Готовы, беги и статус смерти многопоточного чтения Java
Готовное состояние преобразуется в состояние работающего: когда этот поток получает ресурс процессора;
Рабочее состояние преобразуется в состояние готового: когда этот поток активно вызывает метод доходности () или теряет ресурсы процессора во время работы.
Рабочее состояние преобразуется в мертвое состояние: когда тело выполнения потока завершено или происходит исключение.
Здесь следует отметить, что, когда используется метод hield () потока, поток переходит от действующего состояния в состояние готового состояния, но какой поток в состоянии готового процессора запланирована, имеет определенную случайность. Следовательно, может возникнуть, что после того, как потока вызывает метод урожайности (), процессор все еще планирует поток.
Из -за фактических потребностей бизнеса часто встречается, что поток должен быть прекращен с определенной возможностью, чтобы он вошел в мертвое состояние. Наиболее распространенным методом в настоящее время является установка логической переменной, и когда условия будут выполнены, тело выполнения потока будет выполнено быстро. нравиться:
public Class Threadtest {public static void main (string [] args) {myrunnable myrunnable = new myrunnable (); Thread Think = новый поток (myrunnable); for (int i = 0; i <100; i ++) {System.out.println (thread.currentThread (). getName () + "" + i); if (i == 30) {think.start (); } if (i == 40) {myrunnable.stopthread (); }}}} класс MyRunnable Reculsments Runnable {Private Boolean Stop; @Override public void run () {for (int i = 0; i <100 &&! Stop; i ++) {System.out.println (thread.currentThread (). GetName () + "" + i); }} public void stopThread () {this.stop = true; }}В будущем мы будем продолжать разбирать связанные статьи. Спасибо за поддержку этого сайта!
Серия статей:
Объяснение многопоточных экземпляров Java (i)
Подробное объяснение многопоточных экземпляров Java (II)
Подробное объяснение многопоточных экземпляров Java (III)