자바 병렬 프로 그래 밍:스 레 드 를 어떻게 만 듭 니까?
21014 단어 자바 병렬 프로 그래 밍 전재
앞의 글 에 서 는 프로 세 스 와 스 레 드 의 유래 를 다 루 었 습 니 다.오늘 은 자바 에서 스 레 드 를 어떻게 만 드 는 지,스 레 드 로 하여 금 키 임 무 를 수행 하 게 하 는 방법 을 말씀 드 리 겠 습 니 다.자바 의 응용 프로그램 과 프로 세 스 에 관 한 개념 지식 을 먼저 설명 한 다음 에 스 레 드 를 만 드 는 방법 과 프로 세 스 를 만 드 는 방법 을 논술 한다.다음은 본문의 목록 대강 이다.
응용 프로그램 과 프로 세 스 관련 개념
2.자바 에서 스 레 드 를 만 드 는 방법
3.자바 에서 프로 세 스 를 만 드 는 방법
잘못된 점 이 있 으 면 양해 해 주시 고 비판 지적 을 환영 해 주 십시오.
작가 의 노동 성 과 를 존중 하고 전재 하 시 려 면 원문 링크 를 표시 하 십시오.
http://www.cnblogs.com/dolphin0520/p/3913517.html
응용 프로그램 과 프로 세 스 관련 개념
자바 에서 하나의 응용 프로그램 은 JVM 인 스 턴 스(JVM 프로 세 스 라 고도 부 르 는 곳 도 있 습 니 다)에 대응 합 니 다.일반적으로 이름 은 자바.exe 또는 자바 w.exe(windows 에서 작업 관리 자 를 통 해 볼 수 있 습 니 다)입 니 다.자바 는 단일 스 레 드 프로 그래 밍 모델 을 사용 합 니 다.즉,우리 자신의 프로그램 에서 스 레 드 를 주동 적 으로 만 들 지 않 으 면 하나의 스 레 드 만 만 만 듭 니 다.보통 주 스 레 드 라 고 합 니 다.그러나 주의해 야 할 것 은 하나의 스 레 드 만 작업 을 수행 하 는 것 이지 JVM 에 하나의 스 레 드 만 있 는 것 은 아 닙 니 다.JVM 인 스 턴 스 는 생 성 할 때 다른 스 레 드(예 를 들 어 쓰레기 수집 기 스 레 드)를 많이 만 듭 니 다.
자바 는 단일 스 레 드 프로 그래 밍 모델 을 사용 하기 때문에 UI 프로 그래 밍 을 할 때 시간 이 걸 리 는 작업 을 하위 스 레 드 에 두 어 진행 해 야 합 니 다.메 인 스 레 드 를 막 지 않도록 해 야 합 니 다.
2.자바 에서 스 레 드 를 만 드 는 방법
자바 에서 스 레 드 를 만 들 려 면 보통 두 가지 방법 이 있 습 니 다.1)Thread 류 를 계승 합 니 다.2)Runnable 인 터 페 이 스 를 실현 한다.
1.Thread 클래스 계승
Thread 클래스 를 계승 하려 면 run 방법 을 다시 써 야 합 니 다.run 방법 에서 실행 할 작업 을 정의 해 야 합 니 다.
class MyThread extends Thread{
private static int num = 0;
public MyThread(){
num++;
}
@Override
public void run() {
System.out.println(" "+num+" ");
}
}
자신의 스 레 드 클래스 를 만 든 후에 스 레 드 대상 을 만 들 고 start()방법 으로 스 레 드 를 시작 할 수 있 습 니 다.run()방법 으로 스 레 드 를 시작 하 는 것 이 아 닙 니 다.run 방법 에 서 는 실행 해 야 할 작업 만 정의 합 니 다.run 방법 을 호출 하면 주 스 레 드 에서 run 방법 을 실행 하 는 것 과 같 습 니 다.일반적인 방법 으로 호출 하 는 것 과 다 르 지 않 습 니 다.이 때 는 새로운 스 레 드 를 만들어 정 의 를 수행 하지 않 습 니 다.
public class Test {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
class MyThread extends Thread{
private static int num = 0;
public MyThread(){
num++;
}
@Override
public void run() {
System.out.println(" "+num+" ");
}
}
start()방법 을 호출 하면 새로운 스 레 드 를 만 들 수 있 습 니 다.start()방법 호출 과 run()방법 호출 의 차 이 를 구분 하기 위해 다음 예 를 보십시오.
public class Test {
public static void main(String[] args) {
System.out.println(" ID:"+Thread.currentThread().getId());
MyThread thread1 = new MyThread("thread1");
thread1.start();
MyThread thread2 = new MyThread("thread2");
thread2.run();
}
}
class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name = name;
}
@Override
public void run() {
System.out.println("name:"+name+" ID:"+Thread.currentThread().getId());
}
}
실행 결과:
출력 결과 에서 다음 과 같은 결론 을 얻 을 수 있다.
1)thread 1 은 thread 2 의 스 레 드 ID 와 달리 thread 2 는 메 인 스 레 드 ID 와 같 습 니 다.run 방법 으로 호출 하면 새로운 스 레 드 를 만 들 지 않 고 메 인 스 레 드 에서 run 방법 을 직접 실행 하 며 일반적인 방법 으로 호출 하 는 것 과 다 르 지 않 습 니 다.
2)thread 1 의 start 방법 은 thread 2 의 run 방법 앞에서 호출 되 지만 먼저 thread 2 의 run 방법 호출 에 관 한 정 보 를 출력 합 니 다.새 스 레 드 생 성 과정 이 주 스 레 드 의 후속 실행 을 막 지 않 음 을 설명 합 니 다.
2.Runnable 인터페이스 구현
자바 에서 스 레 드 를 만 드 는 것 은 Thread 클래스 를 계승 하 는 것 외 에 도 Runnable 인 터 페 이 스 를 실현 하여 유사 한 기능 을 실현 할 수 있 습 니 다.Runnable 인 터 페 이 스 를 실현 하려 면 run 방법 을 다시 써 야 합 니 다.
다음은 하나.
public class Test {
public static void main(String[] args) {
System.out.println(" ID:"+Thread.currentThread().getId());
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
class MyRunnable implements Runnable{
public MyRunnable() {
}
@Override
public void run() {
System.out.println(" ID:"+Thread.currentThread().getId());
}
}
Runnable 의 중국어 뜻 은'임무'입 니 다.말 그대로 Runnable 인 터 페 이 스 를 실현 함으로써 우 리 는 하위 임 무 를 정의 한 다음 에 하위 임 무 를 Thread 에 맡 깁 니 다.이 방식 은 Runnable 을 Thread 류 의 매개 변수 로 한 다음 Thread 의 start 방법 으로 새 스 레 드 를 만들어 서 이 하위 작업 을 수행 해 야 합 니 다.Runnable 의 run 방법 을 호출 하면 새 스 레 드 를 만 들 지 않 습 니 다.이 일반적인 방법 은 다 르 지 않 습 니 다.
사실 Thread 류 의 실현 소스 코드 를 보면 Thread 류 가 Runnable 인 터 페 이 스 를 실현 한 것 을 발견 할 수 있 습 니 다.
자바 에서 이 두 가지 방식 은 모두 스 레 드 를 만들어 하위 작업 을 수행 할 수 있 습 니 다.구체 적 으로 어떤 방식 을 선택 하 느 냐 에 따라 자신의 요 구 를 볼 수 있 습 니 다.Thread 클래스 를 직접 계승 하면 Runnable 인 터 페 이 스 를 실현 하 는 것 보다 더 간결 해 보일 수 있 지만 자바 가 단일 계승 만 허용 하기 때문에 사용자 정의 클래스 가 다른 클래스 를 계승 해 야 한다 면 Runnable 인 터 페 이 스 를 실현 하 는 것 만 선택 할 수 있 습 니 다.
3.자바 에서 프로 세 스 를 만 드 는 방법
자바 에 서 는 두 가지 방식 으로 프로 세 스 를 만 들 수 있 으 며,모두 5 개의 주요 클래스 와 관련된다.
첫 번 째 방법 은 Runtime.exec()방법 으로 프로 세 스 를 만 드 는 것 이 고,두 번 째 방법 은 ProcessBuilder 의 start 방법 으로 프로 세 스 를 만 드 는 것 입 니 다.다음은 이 두 가지 방식 의 차이 와 관 계 를 살 펴 보 자.
먼저 말 해 야 할 것 은 Process 류 이 고 Process 류 는 추상 류 이다.그 안에 몇 가지 추상 적 인 방법 이 있다.이것 은 Process 류 의 소스 코드 를 보면 알 수 있다.
java.lang.Process 경로 아래 에 있 습 니 다:
public abstract class Process
{
abstract public OutputStream getOutputStream(); //
abstract public InputStream getInputStream(); //
abstract public InputStream getErrorStream(); //
abstract public int waitFor() throws InterruptedException; //
abstract public int exitValue(); //
abstract public void destroy(); //
}
1)ProcessBuilder 를 통 해 프로 세 스 를 만 듭 니 다.ProcessBuilder 는 final 클래스 입 니 다.두 개의 구조 기 가 있 습 니 다.
public final class ProcessBuilder
{
private List command;
private File directory;
private Map environment;
private boolean redirectErrorStream;
public ProcessBuilder(List command) {
if (command == null)
throw new NullPointerException();
this.command = command;
}
public ProcessBuilder(String... command) {
this.command = new ArrayList(command.length);
for (String arg : command)
this.command.add(arg);
}
}
구조 기 는 만들어 야 할 프로 세 스 의 명령 매개 변 수 를 전달 합 니 다.첫 번 째 구조 기 는 명령 매개 변 수 를 List 에 넣 고 전달 하 는 것 입 니 다.두 번 째 구조 기 는 정 해 지지 않 은 긴 문자열 로 전 달 됩 니 다.
그러면 우 리 는 이어서 아래 를 살 펴 보 겠 습 니 다.앞에서 언급 한 것 은 ProcessBuilder 의 start 방법 을 통 해 새로운 프로 세 스 를 만 드 는 것 입 니 다.start 방법 에서 구체 적 으로 어떤 일 을 했 는 지 살 펴 보 겠 습 니 다.다음은 start 방법의 구체 적 인 실현 소스 코드 입 니 다.
public Process start() throws IOException {
// Must convert to array first -- a malicious user-supplied
// list might try to circumvent the security check.
String[] cmdarray = command.toArray(new String[command.size()]);
for (String arg : cmdarray)
if (arg == null)
throw new NullPointerException();
// Throws IndexOutOfBoundsException if command is empty
String prog = cmdarray[0];
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkExec(prog);
String dir = directory == null ? null : directory.toString();
try {
return ProcessImpl.start(cmdarray,
environment,
dir,
redirectErrorStream);
} catch (IOException e) {
// It's much easier for us to create a high-quality error
// message than the low-level C code which found the problem.
throw new IOException(
"Cannot run program \"" + prog + "\""
+ (dir == null ? "" : " (in directory \"" + dir + "\")")
+ ": " + e.getMessage(),
e);
}
}
이 방법 은 Process 대상 을 되 돌려 줍 니 다.이 방법의 앞부분 은 명령 매개 변수 와 설 정 된 작업 디 렉 터 리 에 따라 매개 변 수 를 설정 하 는 것 과 같 습 니 다.가장 중요 한 것 은 try 구문 블록 에 있 는 한 마디 입 니 다.
return ProcessImpl.start(cmdarray,
environment,
dir,
redirectErrorStream);
프로 세 스 를 진정 으로 만 드 는 것 은 이 문장 입 니 다.프로 세 스 Impl 류 의 start 방법 을 호출 하 는 것 을 주의 하 십시오.start 는 반드시 정적 인 방법 임 을 알 수 있 습 니 다.그렇다면 프로 세 스 임 플 은 어떤 부류 일 까?이 클래스 역시 java.lang.ProcessImpl 경로 에 있 습 니 다.이 클래스 의 구체 적 인 실현 을 보십시오.
ProcessImpl 도 final 클래스 로 Process 클래스 를 계승 합 니 다.
final class ProcessImpl extends Process {
// System-dependent portion of ProcessBuilder.start()
static Process start(String cmdarray[],
java.util.Map environment,
String dir,
boolean redirectErrorStream)
throws IOException
{
String envblock = ProcessEnvironment.toEnvironmentBlock(environment);
return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream);
}
....
}
이것 은 ProcessImpl 류 의 start 방법의 구체 적 인 실현 이 며,사실상 start 방법 에 서 는 이 문장 을 통 해 ProcessImpl 대상 을 만 듭 니 다.
1 return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream); 한편,ProcessImpl 에서 Process 류 중의 몇 가지 추상 적 인 방법 에 대해 구체 적 으로 실현 했다.
사실상 ProcessBuilder 의 start 방법 을 통 해 ProcessImpl 대상 을 만 들 었 다 는 뜻 이다.
프로 세 스 빌 더 를 사용 하여 프로 세 스 를 만 드 는 예 를 들 어 프로 세 스 빌 더 를 통 해 cmd 를 열 고 ip 주소 정 보 를 얻 으 려 면 이렇게 쓸 수 있 습 니 다.
public class Test {
public static void main(String[] args) throws IOException {
ProcessBuilder pb = new ProcessBuilder("cmd","/c","ipconfig/all");
Process process = pb.start();
Scanner scanner = new Scanner(process.getInputStream());
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
scanner.close();
}
}
첫 번 째 단 계 는 가장 중요 한 것 입 니 다.명령 문자열 을 ProcessBuilder 의 구조 기 에 전달 하 는 것 입 니 다.일반적으로 문자열 에 있 는 모든 독립 된 명령 을 하나의 매개 변수 로 하지만 순서대로 List 에 넣 어 전달 할 수도 있 습 니 다.
다른 많은 구체 적 인 용법 은 여기 서 군말 하지 않 습 니 다.예 를 들 어 ProcessBuilder 의 environment 방법 과 directory(File directory)를 통 해 프로 세 스 의 환경 변수 와 작업 디 렉 터 리 를 설정 하 는 등 관심 이 있 는 친 구 는 관련 API 문 서 를 볼 수 있 습 니 다.
2)Runtime 의 exec 방법 으로 프로 세 스 만 들 기
우선 Runtime 류 와 exec 방법의 구체 적 인 실현 을 살 펴 보 자.Runtime 은 말 그대로 실행 할 때 현재 프로 세 스 가 있 는 가상 컴퓨터 인 스 턴 스 를 나타 낸다.
모든 프로 세 스 가 하나의 가상 컴퓨터 인 스 턴 스 에서 만 실행 되 기 때문에 Runtime 에서 하나의 가상 컴퓨터 인 스 턴 스 만 생 성 합 니 다.
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class Runtime
are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the Runtime
object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
...
}
이 를 통 해 알 수 있 듯 이 Runtime 류 의 구조 기 는 private 이기 때문에 getRuntime 을 통 해 Runtime 의 인 스 턴 스 를 얻 을 수 있 습 니 다.다음은 exec 방법 실현 에 중심 을 두 고 Runtime 에서 여러 개의 exec 의 서로 다른 재 업로드 실현 이 있 지만 마지막 으로 실 행 된 것 은 이 버 전의 exec 방법 입 니 다.
public Process exec(String[] cmdarray, String[] envp, File dir)
throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
실제로 Runtime 류 의 exec 를 통 해 프로 세 스 를 만 들 면 결국 ProcessBuilder 류 의 start 방법 으로 만 들 어 졌 음 을 알 수 있 습 니 다.
다음 예 를 들 어 Runtime 의 exec 를 통 해 프로 세 스 를 어떻게 만 드 는 지,아니면 앞의 예 를 들 어 cmd 를 호출 하여 ip 주소 정 보 를 얻 는 지 보 겠 습 니 다.
public class Test {
public static void main(String[] args) throws IOException {
String cmd = "cmd "+"/c "+"ipconfig/all";
Process process = Runtime.getRuntime().exec(cmd);
Scanner scanner = new Scanner(process.getInputStream());
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
scanner.close();
}
}
주의해 야 할 것 은 exec 방법 은 부정 확 한 파 라 메 터 를 지원 하지 않 기 때문에 명령 파 라 메 터 를 연결 한 다음 에 전송 해 야 합 니 다.
자바 에서 스 레 드 와 프로 세 스 를 어떻게 만 드 는 지 에 대해 서 는 잠시 이렇게 많은 이 야 기 를 나 누 었 습 니 다.관심 이 있 는 친 구 는 관련 자 료 를 참고 할 수 있 습 니 다.
참고 자료:
http://luckykapok918.blog.163.com/blog/static/205865043201210272168556/
http://www.cnblogs.com/ChrisWang/archive/2009/12/02/use-java-lang-process-and-processbuilder-to-create-native-application-process.html
http://lavasoft.blog.51cto.com/62575/15662/
《자바 프로 그래 밍 사상》.
저자:해자 출처:http://www.cnblogs.com/dolphin0520/ 본 블 로그 에 게재 되 지 않 은 글 은 저자 해자 와 블 로그 원 이 공유 하고 있 으 며,전 재 를 환영 합 니 다.그러나 작가 의 동의 없 이 는 이 성명 을 보류 하고 글 페이지 의 뚜렷 한 위치 에서 원문 연결 을 해 야 합 니 다.그렇지 않 으 면 법 적 책임 을 추궁 할 권 리 를 보류 합 니 다.