자바-멀티 스레딩

Java는 다중 스레드 프로그래밍 언어 이므로 Java를 사용하여 다중 스레드 프로그램을 개발할 수 있습니다. 다중 스레드 프로그램에는 동시에 실행할 수있는 두 개 이상의 부분이 포함되어 있으며 각 부분은 특히 컴퓨터에 여러 CPU가있는 경우 사용 가능한 리소스를 최적으로 사용하여 동시에 다른 작업을 처리 할 수 ​​있습니다.

정의에 따라 멀티 태스킹은 여러 프로세스가 CPU와 같은 공통 처리 리소스를 공유하는 경우입니다. 멀티 스레딩은 멀티 태스킹 개념을 단일 애플리케이션 내의 특정 작업을 개별 스레드로 세분화 할 수있는 애플리케이션으로 확장합니다. 각 스레드는 병렬로 실행될 수 있습니다. OS는 처리 시간을 서로 다른 응용 프로그램뿐만 아니라 응용 프로그램 내의 각 스레드간에 나눕니다.

멀티 스레딩을 사용하면 동일한 프로그램에서 여러 활동을 동시에 진행할 수있는 방식으로 작성할 수 있습니다.

스레드의 수명주기

스레드는 수명주기에서 다양한 단계를 거칩니다. 예를 들어 스레드가 생성되고 시작되고 실행 된 다음 죽습니다. 다음 다이어그램은 스레드의 전체 수명주기를 보여줍니다.

다음은 라이프 사이클의 단계입니다.

  • New− 새 스레드는 새 상태에서 수명주기를 시작합니다. 프로그램이 스레드를 시작할 때까지이 상태로 유지됩니다. 또한born thread.

  • Runnable− 새로 태어난 스레드가 시작된 후 스레드가 실행 가능해집니다. 이 상태의 스레드는 작업을 실행하는 것으로 간주됩니다.

  • Waiting− 때때로 스레드는 다른 스레드가 작업을 수행하기를 기다리는 동안 대기 상태로 전환됩니다. 스레드는 다른 스레드가 대기중인 스레드에 계속 실행하도록 신호를 보낼 때만 실행 가능 상태로 다시 전환됩니다.

  • Timed Waiting− 실행 가능한 스레드는 지정된 시간 간격 동안 시간 대기 상태에 들어갈 수 있습니다. 이 상태의 스레드는 해당 시간 간격이 만료되거나 대기중인 이벤트가 발생하면 다시 실행 가능 상태로 전환됩니다.

  • Terminated (Dead) − 실행 가능한 스레드는 작업을 완료하거나 그렇지 않으면 종료 될 때 종료 됨 상태가됩니다.

스레드 우선 순위

모든 Java 스레드에는 운영 체제가 스레드가 예약되는 순서를 결정하는 데 도움이되는 우선 순위가 있습니다.

Java 스레드 우선 순위는 MIN_PRIORITY (상수 1)와 MAX_PRIORITY (상수 10) 사이의 범위에 있습니다. 기본적으로 모든 스레드에는 우선 순위 NORM_PRIORITY (상수 5)가 지정됩니다.

우선 순위가 높은 스레드는 프로그램에 더 중요하며 우선 순위가 낮은 스레드보다 먼저 프로세서 시간을 할당해야합니다. 그러나 스레드 우선 순위는 스레드가 실행되는 순서를 보장 할 수 없으며 플랫폼에 따라 크게 달라집니다.

실행 가능한 인터페이스를 구현하여 스레드 생성

클래스가 스레드로 실행되도록 의도 된 경우 다음을 구현하여이를 달성 할 수 있습니다. Runnable상호 작용. 세 가지 기본 단계를 따라야합니다.

1 단계

첫 번째 단계로 a에서 제공하는 run () 메서드를 구현해야합니다. Runnable상호 작용. 이 메서드는 스레드에 대한 진입 점을 제공하며이 메서드 안에 완전한 비즈니스 논리를 넣습니다. 다음은 run () 메서드의 간단한 구문입니다.

public void run( )

2 단계

두 번째 단계로 Thread 다음 생성자를 사용하여 객체-

Thread(Runnable threadObj, String threadName);

여기서 threadObj 는 다음을 구현하는 클래스의 인스턴스입니다.Runnable 인터페이스 및 threadName 새 스레드에 주어진 이름입니다.

3 단계

Thread 객체가 생성되면 다음을 호출하여 시작할 수 있습니다. start()메서드는 run () 메서드에 대한 호출을 실행합니다. 다음은 start () 메서드의 간단한 구문입니다.

void start();

다음은 새 스레드를 만들고 실행을 시작하는 예입니다.

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

이것은 다음 결과를 생성합니다-

산출

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

스레드 클래스를 확장하여 스레드 만들기

스레드를 만드는 두 번째 방법은 확장하는 새 클래스를 만드는 것입니다. Thread다음 두 가지 간단한 단계를 사용하여 클래스. 이 접근 방식은 Thread 클래스에서 사용 가능한 메서드를 사용하여 생성 된 여러 스레드를 처리하는 데 더 많은 유연성을 제공합니다.

1 단계

재정의해야합니다. run( )Thread 클래스에서 사용할 수있는 메서드. 이 메서드는 스레드에 대한 진입 점을 제공하며이 메서드 안에 완전한 비즈니스 논리를 넣습니다. 다음은 run () 메소드의 간단한 구문입니다.

public void run( )

2 단계

Thread 객체가 생성되면 다음을 호출하여 시작할 수 있습니다. start()메서드는 run () 메서드에 대한 호출을 실행합니다. 다음은 start () 메서드의 간단한 구문입니다.

void start( );

다음은 스레드를 확장하기 위해 재 작성된 이전 프로그램입니다.

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

이것은 다음 결과를 생성합니다-

산출

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

스레드 방법

다음은 Thread 클래스에서 사용할 수있는 중요한 메서드 목록입니다.

Sr. 아니. 방법 및 설명
1

public void start()

별도의 실행 경로에서 스레드를 시작한 다음이 Thread 객체에서 run () 메서드를 호출합니다.

2

public void run()

이 Thread 객체가 별도의 Runnable 대상을 사용하여 인스턴스화 된 경우 해당 Runnable 객체에서 run () 메서드가 호출됩니다.

public final void setName(String name)

Thread 개체의 이름을 변경합니다. 이름을 검색하기위한 getName () 메소드도 있습니다.

4

public final void setPriority(int priority)

이 Thread 객체의 우선 순위를 설정합니다. 가능한 값은 1에서 10 사이입니다.

5

public final void setDaemon(boolean on)

true 매개 변수는이 스레드를 데몬 스레드로 나타냅니다.

6

public final void join(long millisec)

현재 스레드는 두 번째 스레드에서이 메서드를 호출하여 두 번째 스레드가 종료되거나 지정된 밀리 초가 경과 할 때까지 현재 스레드를 차단합니다.

7

public void interrupt()

이 스레드를 중단하여 어떤 이유로 든 차단 된 경우 계속 실행되도록합니다.

8

public final boolean isAlive()

스레드가 활성화 된 경우 true를 반환합니다. 이는 스레드가 시작된 후 완료되기 전의 시간입니다.

이전 메서드는 특정 Thread 개체에서 호출됩니다. Thread 클래스의 다음 메서드는 정적입니다. 정적 메서드 중 하나를 호출하면 현재 실행중인 스레드에서 작업이 수행됩니다.

Sr. 아니. 방법 및 설명
1

public static void yield()

현재 실행중인 스레드가 예약 대기중인 동일한 우선 순위의 다른 스레드에 양보하도록합니다.

2

public static void sleep(long millisec)

현재 실행중인 스레드가 지정된 밀리 초 이상 차단되도록합니다.

public static boolean holdsLock(Object x)

현재 스레드가 지정된 Object에 대한 잠금을 보유하고 있으면 true를 반환합니다.

4

public static Thread currentThread()

이 메서드를 호출하는 스레드 인 현재 실행중인 스레드에 대한 참조를 반환합니다.

5

public static void dumpStack()

현재 실행중인 스레드에 대한 스택 추적을 인쇄합니다. 이는 다중 스레드 애플리케이션을 디버깅 할 때 유용합니다.

다음 ThreadClassDemo 프로그램은 Thread 클래스의 이러한 메서드 중 일부를 보여줍니다. 수업 고려DisplayMessage 구현하는 Runnable

// File Name : DisplayMessage.java
// Create a thread to implement Runnable

public class DisplayMessage implements Runnable {
   private String message;
   
   public DisplayMessage(String message) {
      this.message = message;
   }
   
   public void run() {
      while(true) {
         System.out.println(message);
      }
   }
}

다음은 Thread 클래스를 확장하는 또 다른 클래스입니다.

// File Name : GuessANumber.java
// Create a thread to extentd Thread

public class GuessANumber extends Thread {
   private int number;
   public GuessANumber(int number) {
      this.number = number;
   }
   
   public void run() {
      int counter = 0;
      int guess = 0;
      do {
         guess = (int) (Math.random() * 100 + 1);
         System.out.println(this.getName() + " guesses " + guess);
         counter++;
      } while(guess != number);
      System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
   }
}

다음은 위에 정의 된 클래스를 사용하는 주요 프로그램입니다.

// File Name : ThreadClassDemo.java
public class ThreadClassDemo {

   public static void main(String [] args) {
      Runnable hello = new DisplayMessage("Hello");
      Thread thread1 = new Thread(hello);
      thread1.setDaemon(true);
      thread1.setName("hello");
      System.out.println("Starting hello thread...");
      thread1.start();
      
      Runnable bye = new DisplayMessage("Goodbye");
      Thread thread2 = new Thread(bye);
      thread2.setPriority(Thread.MIN_PRIORITY);
      thread2.setDaemon(true);
      System.out.println("Starting goodbye thread...");
      thread2.start();

      System.out.println("Starting thread3...");
      Thread thread3 = new GuessANumber(27);
      thread3.start();
      try {
         thread3.join();
      } catch (InterruptedException e) {
         System.out.println("Thread interrupted.");
      }
      System.out.println("Starting thread4...");
      Thread thread4 = new GuessANumber(75);
      
      thread4.start();
      System.out.println("main() is ending...");
   }
}

그러면 다음과 같은 결과가 생성됩니다. 이 예제를 반복해서 시도 할 수 있으며 매번 다른 결과를 얻을 수 있습니다.

산출

Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......

주요 Java 멀티 스레딩 개념

Java에서 멀티 스레딩 프로그래밍을 수행하는 동안 다음 개념이 매우 편리해야합니다.

  • 스레드 동기화 란 무엇입니까?

  • 스레드 간 통신 처리

  • 스레드 교착 상태 처리

  • 주요 스레드 작업