Во -первых, давайте поговорим о концептуальных знаниях, связанных с приложениями и процессами в Java, а затем объясним, как создавать потоки и как создавать процессы. Вот контур каталогов этой статьи:
1. Концепции, связанные с приложениями и процессами на Java
2. Как создать потоки на Java
3. Как создать процесс на Java
1. Концепции, связанные с приложениями и процессами на Java
В Java приложение соответствует экземпляру JVM (также называемому процессу JVM), и имя по умолчанию по умолчанию Java.exe или Javaw.exe (можно просматривать через диспетчер задач под Windows). Java принимает однопоточную модель программирования, то есть, если мы не будем активно создавать потоки в нашей собственной программе, мы создадим только один поток, который обычно называют основным потоком. Но имейте в виду, что, хотя есть только один поток для выполнения задач, не означает, что в JVM есть только один поток. При создании экземпляра JVM будет создано много других потоков (например, потоки коллектора мусора).
Поскольку Java принимает однопоточную модель программирования, при программировании пользовательского интерфейса, вы должны обратить внимание на то, чтобы поместить много времени в детском потоке, чтобы избежать блокировки основного потока (при программировании пользовательского интерфейса, основной поток-поток пользовательского интерфейса, который используется для обработки событий взаимодействия пользователя).
2. Как создать потоки на Java
Если вы хотите создать поток в Java, обычно есть два способа: 1) наследуйте класс потоков; 2) Реализуйте запускаемый интерфейс.
1. Унаследовать класс потоков
Если вы наследуете класс потоков, вы должны переопределить метод выполнения и определить задачи, которые необходимо выполнять в методе выполнения.
класс Mythread Extends Thread {Private Static int num = 0; public mythread () {num ++; } @Override public void run () {System.out.println ("активно создан"+num+"потоки"); }}После создания собственного класса потоков вы можете создать объект потока, а затем запустить поток через метод start (). Обратите внимание, что он не называется методом run () для запуска потока. Метод выполнения определяет только задачи, которые необходимо выполнить. Если метод выполнения вызывается, он эквивалентен выполнению метода выполнения в основном потоке, который не отличается от обычных вызовов метода. В настоящее время не будет создан новый поток для выполнения определенных задач.
открытый тест класса {public static void main (string [] args) {mythread Thread = new Mythread (); Thread.Start (); }} класс Mythread Extends Thread {private static int num = 0; public mythread () {num ++; } @Override public void run () {System.out.println ("активно создан"+num+"потоки"); }}В приведенном выше коде, вызовом метода Start (), будет создан новый поток. Чтобы различить разницу между вызовами метода start () и вызовы метода run (), см. В следующем примере:
открытый тест класса {public static void main (string [] args) {System.out.println ("Основной идентификатор потока:"+thread.currentthread (). getId ()); Mythread Thread1 = New Mythread ("Thread1"); Thread1.start (); Mythread thread2 = new Mythread ("Thread2"); Thread2.run (); }} класс Mythread Extends Thread {Private String name; public mythread (string name) {this.name = name; } @Override public void run () {System.out.println ("name:"+name+"идентификатор детского потока:"+thread.currentThread (). GetId ()); }}Результаты работы:
Из выходных результатов можно сделать следующие выводы:
1) идентификаторы потока Thread1 и Think2 различны, а Thread2 и основной идентификатор потока одинаковы, что означает, что вызов метода выполнения не создаст новый поток, но напрямую запускает метод выполнения в основном потоке, что ничем не отличается от обычных вызовов метода;
2) Несмотря на то, что метод начала вызова потока 1 вызовов перед методом запуска Thread2, информация о вызове метода запуска Thread2 сначала выводится, что указывает на то, что процесс создания нового потока не будет блокировать последующее выполнение основного потока.
2. Реализуйте запускаемый интерфейс
В дополнение к унаследованию класса потоков, создание потоков в Java также может реализовать аналогичные функции, реализуя выполняемый интерфейс. Реализация запускаемого интерфейса должна переопределить метод выполнения.
Вот пример:
открытый тест класса {public static void main (string [] args) {System.out.println ("Основной идентификатор потока:"+thread.currentthread (). getId ()); Myrunnable runnable = new myrunnable (); Thread Think = New Thread (Runnable); Thread.Start (); }} класс myrunnable реализации runnable {public myrunnable () {} @Override public void run () {System.out.println ("subthread id:"+thread.currentThread (). getId ()); }}Забегаемое означает «задача» на китайском языке. Как следует из названия, реализуя запускаемый интерфейс, мы определяем подзадачу, а затем передаем подзадачу, чтобы выполнить поток. Обратите внимание, что этот метод должен использовать выполнение в качестве параметра для класса потока, а затем создать новый поток для выполнения подзадачи через метод запуска потока. Если вызовут метод выполнения, вызову, новый поток не будет создан, и между этим обычным вызовом метода нет никакой разницы.
На самом деле, если вы посмотрите на исходный код реализации класса потока, вы обнаружите, что класс потоков реализует запускаемый интерфейс.
В Java эти два метода могут использоваться для создания потоков для выполнения подзадач. Конкретный метод для выбора зависит от ваших потребностей. Если вы непосредственно наследуете класс потоков, он может выглядеть более кратким, чем реализация запускаемого интерфейса. Однако, поскольку Java допускает только единственное наследование, если пользовательский класс должен наследовать другие классы, вы можете только реализовать выполняемый интерфейс.
3. Как создать процесс на Java
В Java есть два способа создания процессов, включающих в общей сложности 5 основных классов.
Первым методом является создание процесса с помощью метода Runtime.exec (), а второй метод - создать процесс с помощью метода начала процесса. Давайте поговорим о различиях и связях между этими двумя методами.
Первое, о чем я хочу поговорить, это процесс класса. Класс процессов - это абстрактный класс. В нем есть в основном несколько абстрактных методов. Вы можете узнать это, посмотрев на исходный код класса процесса:
Расположен в пути Java.lang.process:
открытый тест класса {public static void main (string [] args) {System.out.println ("Основной идентификатор потока:"+thread.currentthread (). getId ()); Myrunnable runnable = new myrunnable (); Thread Think = New Thread (Runnable); Thread.Start (); }} класс myrunnable реализации runnable {public myrunnable () {} @Override public void run () {System.out.println ("subthread id:"+thread.currentThread (). getId ()); }}1) Создать процесс через процесс построения
ProcessBuilder - это последний класс, который имеет два конструктора:
Public Final Class ProcessBuilder {Private List <string> Command; Частный файловый каталог; частная карта <строка, строка> среда; Частный логический Redirecterrorsream; public ProcessBuilder (list <string> command) {if (command == null) бросить новый NullPointerException (); this.command = command; } public ProcessBuilder (string ... command) {this.command = new ArrayList <string> (command.length); for (String arg: command) this.command.add (arg); } ......}Конструктор передает параметры команды процесса, который необходимо создать. Первый конструктор помещает параметры команды в список и передает их в виде неопределенной длинной строки.
Итак, давайте продолжим смотреть вниз. Как упоминалось ранее, мы создаем новый процесс с помощью метода начала процессора. Давайте посмотрим, что именно делается в методе начала. Ниже приведено конкретный исходный код реализации метода начала:
public Process start () бросает ioException {// Сначала преобразовать в массив-злой пользователь-поставлен // Список может попытаться привести к сплошным веществам. является пустым стрижкой prog = cmdarray [0]; SecurityManager Security = System.GetSecurityManager (); if (Security! = NULL) Security.CHECKEXEC (PROG); String dir = каталог == null? null: directory.tostring (); try {return processimpl.start (cmdarray, Environment, Dir, Redirecterrorsream);} Catch (ioException e) {// Нам намного проще создать высококачественную ошибку //, чем низкоуровневый код C, который нашла проблему. Бросьте новое ioexception («Невозможно запустить программу /» « + prog +» /"" + (dir == null? "": "(в каталоге /" " + dir +" /")") + ":" + e.getMessage (), e);}}Этот метод возвращает объект процесса. Первая часть метода эквивалентна настройке некоторых параметров на основе параметров команды и установленного рабочего каталога. Самое главное - это предложение в блоке оператора TRY:
return ProcessImpl.Start (Cmdarray, Environment, Dir, RedireCterrorStream);
Это предложение, которое действительно создает процесс. Обратите внимание, что метод начала класса ProcessImpl вызывается. Здесь мы можем знать, что старт должен быть статическим методом. Итак, что такое ProcessImpl? Этот класс также находится на пути Java.lang.processimpl. Давайте посмотрим на конкретную реализацию этого класса:
ProcessImpl также является окончательным классом, который наследует класс процесса:
Окончательный класс ProcessImpl Extends Process {// Система-зависимая часть ProcessBuilder.Start () Static Process Start (String cmdarray [], java.util.map <String, String> Environment, String Dir, Boolean RedireCterrorStream) Throws IOException {String Envblock = ProcessEnvOradmentBlock (Environmental); вернуть новый ProcessImpl (Cmdarray, Envblock, Dir, RedireCterrorStream); } ....}Это конкретная реализация метода начала класса ProcessImpl. Фактически, это предложение используется для создания объекта ProcessImpl:
вернуть новый ProcessImpl (Cmdarray, Envblock, Dir, RedireCterrorStream);
В ProcessImpl несколько абстрактных методов в классе процесса реализованы в конкретной реализации.
Фактически, объект ProcessImpl создается с помощью метода начала процесса -строителя.
Давайте посмотрим на пример использования процесса -строителя для создания процесса. Например, если я хочу запустить процесс через процесс, чтобы открыть CMD и получить информацию о IP -адресах, я могу написать его так:
Общедоступный тест класса {public static void main (string [] args) бросает ioException {processBuilder pb = new ProcessBuilder ("cmd", "/c", "ipconfig/all"); Процесс процесса = pb.start (); Сканер сканер = новый сканер (Process.getInputStream ()); while (scanner.hasnextline ()) {system.out.println (scanner.nextline ()); } scanner.close (); }}Первым шагом является наиболее критичным, который состоит в том, чтобы передать строку команды конструктору процесса. Вообще говоря, каждая независимая команда в строке используется в качестве отдельного параметра, но она также может быть помещена в список по порядку и передается.
Что касается многих других конкретных использований, я не буду подробно останавливаться на них здесь, например, установление переменных среды процесса и рабочие каталоги с помощью метода и каталога среды и каталога Environment ProcessBuilder (файловый каталог). Заинтересованные друзья могут просмотреть соответствующие документы API.
2) Создать процесс с помощью метода EXEC Runtime.
Во -первых, давайте посмотрим на конкретную реализацию класса времени выполнения и метода EXEC. Среда выполнения, как следует из названия, означает, что запуск представляет экземпляр виртуальной машины, где находится текущий процесс.
Поскольку любой процесс будет работать только в одном экземпляре виртуальной машины, в среде выполнения используется режим синглтона, то есть будет создан только один экземпляр виртуальной машины:
Public Class Runtime {Private Static Runtime CurrentRuntime = New Runtime (); /*** Возвращает объект времени выполнения, связанный с текущим приложением Java. * Большинство методов класса <code> время выполнения </code> являются методами экземпляра * и должны быть вызваны в отношении текущего объекта времени выполнения. * * @return. <code> runtime </code> объект, связанный с текущим приложением * Java. */ public static runtime getRuntime () {return currentruntime; } / ** Не позволяйте никому экземплятировать этот класс* / private Runtime () {} ...}Отсюда мы видим, что, поскольку конструктор класса времени выполнения является частным, мы можем получить экземпляр выполнения только через getRuntime. Далее давайте внимательно рассмотрим реализацию метода EXEC. Существует несколько различных реализаций перегрузки EXEC в среде выполнения, но окончание выполнения - эта версия метода EXEC:
public Process Exec (String [] cmdarray, String [] envp, файл dir) бросает ioexception {return new ProcessBuilder (cmdarray) .Ervironment (envp) .directory (dir) .start (); }Можно обнаружить, что на самом деле, если процесс создается с помощью EXEC класса времени выполнения, он в конечном итоге создается с помощью метода начала класса процесса.
Давайте посмотрим на пример, чтобы увидеть, как создать процесс через EXEC Runtime или в предыдущем примере, вызовите CMD, чтобы получить информацию о IP -адресе:
открытый тест класса {public static void main (string [] args) бросает ioException {string cmd = "cmd"+"/c"+"ipconfig/all"; Процесс процесса = runtime.getRuntime (). Exec (cmd); Сканер сканер = новый сканер (Process.getInputStream ()); while (scanner.hasnextline ()) {system.out.println (scanner.nextline ()); } scanner.close (); }}Следует отметить, что метод EXEC не поддерживает параметры неопределенной длины (процесс-строитель поддерживает параметры неопределенной длины), поэтому параметры команды должны быть сначала сплайсированы, прежде чем их передавать.
Я расскажу о том, как создавать темы и процессы в Java на данный момент. Заинтересованные друзья могут ссылаться на соответствующую информацию.