Java 동시성-개요

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();

Example

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

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();
   }   
}

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

Output

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( );

Example

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

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();
   }   
}

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

Output

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.