java 기초 강좌의 다선정 상세 및 간단한 실례
이 문장에서 우리는 다선정에 관심을 갖는다.다중 스레드는 복잡한 화제로 많은 내용을 포함하고 있다. 이 글은 주로 스레드의 기본 속성, 어떻게 스레드를 만드는지, 스레드의 상태 전환과 스레드 통신에 주목한다.
루틴은 운영체제가 실행하는 기본 단위로 프로세스에 봉인되어 하나의 프로세스에 여러 개의 루틴을 포함할 수 있다.설령 우리가 수동으로 라인을 만들지 않더라도 프로세스는 기본 라인이 실행될 것이다.
JVM에 대해 말하자면, 우리가 단일 스레드를 작성하여 실행할 때, JVM에도 적어도 두 개의 스레드가 실행되고 있다. 하나는 우리가 만든 프로그램이고, 하나는 쓰레기 수거이다.
스레드 기본 정보
우리는 Thread를 통해currentThread () 메서드는 현재 스레드에 대한 정보를 가져와 수정합니다.
다음 코드를 살펴보겠습니다.
String name = Thread.currentThread().getName();
int priority = Thread.currentThread().getPriority();
String groupName = Thread.currentThread().getThreadGroup().getName();
boolean isDaemon = Thread.currentThread().isDaemon();
System.out.println("Thread Name:" + name);
System.out.println("Priority:" + priority);
System.out.println("Group Name:" + groupName);
System.out.println("IsDaemon:" + isDaemon);
Thread.currentThread().setName("Test");
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
name = Thread.currentThread().getName();
priority = Thread.currentThread().getPriority();
groupName = Thread.currentThread().getThreadGroup().getName();
isDaemon = Thread.currentThread().isDaemon();
System.out.println("Thread Name:" + name);
System.out.println("Priority:" + priority);
여기에 나열된 등록 정보는 다음과 같습니다.
public static void priorityTest()
{
Thread thread1 = new Thread("low")
{
public void run()
{
for (int i = 0; i < 5; i++)
{
System.out.println("Thread 1 is running.");
}
}
};
Thread thread2 = new Thread("high")
{
public void run()
{
for (int i = 0; i < 5; i++)
{
System.out.println("Thread 2 is running.");
}
}
};
thread1.setPriority(Thread.MIN_PRIORITY);
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
운행 결과에서 알 수 있듯이 높은 우선순위 라인이 실행된 후에야 낮은 우선순위 라인이 실행된다.이 속성은 부자 라인의 관계를 제어하는 데 사용됩니다. 만약true로 설정하면 부모 라인이 끝난 후에 그 아래의 모든 하위 라인도 끝납니다. 반대로 하위 라인의 생명 주기는 부모 라인의 영향을 받지 않습니다.
다음 예를 살펴보겠습니다.
IsDaemon
public static void daemonTest()
{
Thread thread1 = new Thread("daemon")
{
public void run()
{
Thread subThread = new Thread("sub")
{
public void run()
{
for(int i = 0; i < 100; i++)
{
System.out.println("Sub Thread Running " + i);
}
}
};
subThread.setDaemon(true);
subThread.start();
System.out.println("Main Thread end.");
}
};
thread1.start();
}
위 코드의 실행 결과,subThread를 삭제하고 있습니다.setDaemon(true);후자를 비교해 보면 후자의 운행 과정에서 서브루틴은 실행을 완성한 후에 끝날 것이고 전자에서 서브루틴은 곧 끝날 것이다.어떻게 라인을 만듭니까
위의 내용은 모두 기본 스레드 중의 일부 정보를 보여 줍니다. 그러면 어떻게 스레드를 만들어야 합니까?Java에서 우리는 세 가지 방식으로 라인을 만들 수 있다.
Java의 스레드는 Thread 클래스를 계승하거나 Runnable 인터페이스를 실현하는 것입니다.
내부 클래스를 사용하여 스레드 만들기
우리는 내부 클래스를 사용하여 라인을 만들 수 있습니다. 프로세스는Thread 형식의 변수를 설명하고 run 방법을 다시 쓰는 것입니다.예제 코드는 다음과 같습니다.
public static void createThreadByNestClass()
{
Thread thread = new Thread()
{
public void run()
{
for (int i =0; i < 5; i++)
{
System.out.println("Thread " + Thread.currentThread().getName() + " is running.");
}
System.out.println("Thread " + Thread.currentThread().getName() + " is finished.");
}
};
thread.start();
}
스레드 생성을 위해 Thread 상속우리는Thread에서 하나의 종류를 파생시켜run방법을 다시 쓸 수 있는데, 이런 방식은 위와 비슷하다.예제 코드는 다음과 같습니다.
Thread
class MyThread extends Thread
{
public void run()
{
for (int i =0; i < 5; i++)
{
System.out.println("Thread " + Thread.currentThread().getName() + " is running.");
}
System.out.println("Thread " + Thread.currentThread().getName() + " is finished.");
}
}
public static void createThreadBySubClass()
{
MyThread thread = new MyThread();
thread.start();
}
루틴 생성을 위한 Runnable 인터페이스 구현우리는 클래스를 정의하여 Runnable 인터페이스를 실현하고 이 클래스의 실례를 Thread 변수 구조 함수를 구축하는 매개 변수로 삼을 수 있다.예제 코드는 다음과 같습니다.
Runnable
class MyRunnable implements Runnable
{
public void run()
{
for (int i =0; i < 5; i++)
{
System.out.println("Thread " + Thread.currentThread().getName() + " is running.");
}
System.out.println("Thread " + Thread.currentThread().getName() + " is finished.");
}
}
public static void createThreadByRunnable()
{
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
상술한 세 가지 방식은 모두 라인을 만들 수 있고 예시 코드에서 볼 때 라인이 실행하는 기능은 같다. 그러면 이 세 가지 창설 방식은 무엇이 다른가?이것은 Java의 다중 스레드 실행 모드와 관련된다. Java의 경우 다중 스레드가 실행될 때'다중 객체 다중 스레드'와'단일 객체 다중 스레드'의 차이가 있다.
다음 예제 코드를 살펴보겠습니다. Object가 사용됩니다.notify 방법, 이 방법은 대상의 라인을 깨울 수 있습니다.Object.notifyAll 메서드는 객체의 모든 스레드를 깨웁니다.
notify
public class NotifySample {
public static void main(String[] args) throws InterruptedException
{
notifyTest();
notifyTest2();
notifyTest3();
}
private static void notifyTest() throws InterruptedException
{
MyThread[] arrThreads = new MyThread[3];
for (int i = 0; i < arrThreads.length; i++)
{
arrThreads[i] = new MyThread();
arrThreads[i].id = i;
arrThreads[i].setDaemon(true);
arrThreads[i].start();
}
Thread.sleep(500);
for (int i = 0; i < arrThreads.length; i++)
{
synchronized(arrThreads[i])
{
arrThreads[i].notify();
}
}
}
private static void notifyTest2() throws InterruptedException
{
MyRunner[] arrMyRunners = new MyRunner[3];
Thread[] arrThreads = new Thread[3];
for (int i = 0; i < arrThreads.length; i++)
{
arrMyRunners[i] = new MyRunner();
arrMyRunners[i].id = i;
arrThreads[i] = new Thread(arrMyRunners[i]);
arrThreads[i].setDaemon(true);
arrThreads[i].start();
}
Thread.sleep(500);
for (int i = 0; i < arrMyRunners.length; i++)
{
synchronized(arrMyRunners[i])
{
arrMyRunners[i].notify();
}
}
}
private static void notifyTest3() throws InterruptedException
{
MyRunner runner = new MyRunner();
Thread[] arrThreads = new Thread[3];
for (int i = 0; i < arrThreads.length; i++)
{
arrThreads[i] = new Thread(runner);
arrThreads[i].setDaemon(true);
arrThreads[i].start();
}
Thread.sleep(500);
synchronized(runner)
{
runner.notifyAll();
}
}
}
class MyThread extends Thread
{
public int id = 0;
public void run()
{
System.out.println(" " + id + " 5 。");
try
{
synchronized(this)
{
this.wait(5*60*1000);
}
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
System.out.println(" " + id + " 。");
}
}
class MyRunner implements Runnable
{
public int id = 0;
public void run()
{
System.out.println(" " + id + " 5 。");
try
{
synchronized(this)
{
this.wait(5*60*1000);
}
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
System.out.println(" " + id + " 。");
}
}
예시 코드에서 notifyTest () 와 notifyTest2 () 는'다중 대상 다중 스레드'입니다. notifyTest2 () 의 스레드가 Runnable 인터페이스를 실현하지만, 그 안에 Thread 그룹을 정의할 때, 모든 요소는 새로운 Runnable 실례를 사용합니다.notifyTest3()는 "단일 대상 다중 스레드"에 속합니다. Runnable 실례만 정의했기 때문에 모든 스레드가 이 실례를 사용합니다.notifyAll 방법은 "단일 대상 다중 스레드"상황에 적용됩니다. 왜냐하면 notify 방법은 무작위로 대상의 한 스레드만 깨울 수 있기 때문입니다.
스레드 상태 전환
스레드에 대해 말하자면, 우리가 그것을 만들어서 스레드 운행이 끝날 때까지 이 과정에서 스레드의 상태는 다음과 같을 수 있다.
스레드 대기 및 깨우기
여기에는 Object가 주로 사용됩니다.wait와 Object.notify 방법, 위의 notify 실례를 참고하십시오.주의해야 할 것은wait와 notify는 모두 같은 대상을 겨냥해야 한다는 것이다. 우리가 Runnable 인터페이스를 실현하는 방식으로 라인을 만들 때,Thread 대상이 아닌 Runnable 대상에서 이 두 가지 방법을 사용해야 한다.
라인의 휴면과 깨우기
Thread.sleep
public class SleepSample {
public static void main(String[] args) throws InterruptedException
{
sleepTest();
}
private static void sleepTest() throws InterruptedException
{
Thread thread = new Thread()
{
public void run()
{
System.out.println(" " + Thread.currentThread().getName() + " 5 。");
try
{
Thread.sleep(5*60*1000);
}
catch(InterruptedException ex)
{
System.out.println(" " + Thread.currentThread().getName() + " 。");
}
System.out.println(" " + Thread.currentThread().getName() + " 。");
}
};
thread.setDaemon(true);
thread.start();
Thread.sleep(500);
thread.interrupt();
}
}
스레드는 휴면 중에 Thread를 사용할 수 있습니다.interrupt에서 깨우십시오. 이 때 라인은 Interrupted Exception을 던집니다.스레드의 종료
스레드가 있지만.stop 방법이지만 이 방법은 추천하지 않습니다. 우리는 위의 휴면과 깨우는 메커니즘을 이용하여 라인이 Iterrupted Exception을 처리할 때 라인을 끝낼 수 있습니다.
Thread.interrupt
public class StopThreadSample {
public static void main(String[] args) throws InterruptedException
{
stopTest();
}
private static void stopTest() throws InterruptedException
{
Thread thread = new Thread()
{
public void run()
{
System.out.println(" 。");
try
{
Thread.sleep(1*60*1000);
}
catch(InterruptedException ex)
{
System.out.println(" , ");
return;
}
System.out.println(" 。");
}
};
thread.start();
Thread.sleep(500);
thread.interrupt();
}
}
스레드의 동기화 대기우리가 메인 라인에서 10개의 하위 라인을 만들었고, 10개의 하위 라인이 모두 끝난 후에 메인 라인이 다음 논리를 실행하기를 기대한다면, 이 때 Thread를 사용해야 한다.조인이 등장했다.
Thread.join
public class JoinSample {
public static void main(String[] args) throws InterruptedException
{
joinTest();
}
private static void joinTest() throws InterruptedException
{
Thread thread = new Thread()
{
public void run()
{
try
{
for(int i = 0; i < 5; i++)
{
System.out.println(" 。");
Thread.sleep(1000);
}
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
Thread.sleep(1000);
thread.join();
System.out.println(" 。");
}
}
우리는thread를 시도해 볼 수 있다.join();주석이나 삭제, 프로그램을 다시 실행하면 다른 것을 발견할 수 있습니다.스레드 간 통신
우리는 하나의 프로세스 아래의 모든 스레드가 메모리 공간을 공유하는 것을 알고 있다. 그러면 우리는 어떻게 서로 다른 스레드 사이에서 정보를 전달합니까?Java I/O를 살펴보면서 PipedStream과 PipedReader에 대해 이야기했습니다. 여기가 바로 그 역할을 하는 곳입니다.
다음 두 가지 예는 기능이 완전히 같다. 하나는 Stream을 사용하고 하나는 Reader/Writer를 사용한다.
PipeInputStream/PipedOutpueStream
public static void communicationTest() throws IOException, InterruptedException
{
final PipedOutputStream pos = new PipedOutputStream();
final PipedInputStream pis = new PipedInputStream(pos);
Thread thread1 = new Thread()
{
public void run()
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try
{
while(true)
{
String message = br.readLine();
pos.write(message.getBytes());
if (message.equals("end")) break;
}
br.close();
pos.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
};
Thread thread2 = new Thread()
{
public void run()
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
try
{
while((bytesRead = pis.read(buffer, 0, buffer.length)) != -1)
{
System.out.println(new String(buffer));
if (new String(buffer).equals("end")) break;
buffer = null;
buffer = new byte[1024];
}
pis.close();
buffer = null;
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
};
thread1.setDaemon(true);
thread2.setDaemon(true);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
PipedReader/PipedWriter
private static void communicationTest2() throws InterruptedException, IOException
{
final PipedWriter pw = new PipedWriter();
final PipedReader pr = new PipedReader(pw);
final BufferedWriter bw = new BufferedWriter(pw);
final BufferedReader br = new BufferedReader(pr);
Thread thread1 = new Thread()
{
public void run()
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try
{
while(true)
{
String message = br.readLine();
bw.write(message);
bw.newLine();
bw.flush();
if (message.equals("end")) break;
}
br.close();
pw.close();
bw.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
};
Thread thread2 = new Thread()
{
public void run()
{
String line = null;
try
{
while((line = br.readLine()) != null)
{
System.out.println(line);
if (line.equals("end")) break;
}
br.close();
pr.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
};
thread1.setDaemon(true);
thread2.setDaemon(true);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.