Development

[JAVA] Thread 사용해보기 - Thread / Runnable 예제 본문

Languages/JAVA

[JAVA] Thread 사용해보기 - Thread / Runnable 예제

yo~og 2021. 11. 17. 14:11
반응형

오늘은 스레드의 개념과 자바에서의 스레드 사용법을 알아봅시다!

 

스레드는 프로세스 내에서 실행되는 흐름의 단위를 말합니다. 일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있습니다.

 

자바에서의 스레드는 main()안의 실행문들이 하나의 스레드입니다.

main()이외의 스레드를 만들려면 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현해야합니다.

 

두 방법을 모두 알아봅시다!


1. Thread 클래스 상속

 

DownloadThread.java

package test.mypac;
/*
 * 새로운 스레드 만드는 방법
 * 
 * 1. Thread 클래스를 상속 받은 클래스를 정의한다.
 * 2. run() 메소드를 오버라이드한다.
 * 3. run() 메소드 안에서 새로운 스레드에서 해야할 작업을 코딩한다.
 * 4. 만든 클래스로 객체를 생성하고 해당 객체의 start() 메소드를 호출하면 새로운 스레드가 시작된다.
 */
public class DownloadThread extends Thread{

	@Override
	public void run() {
	      //완료하는데 10초가 걸리는 작업을 한다고 가정하자
	      try {
	         Thread.sleep(10000);
	         System.out.println("다운로드가 완료 되었습니다.");
	      } catch (InterruptedException e1) {
	         e1.printStackTrace();
	      }
	}
	

}

main.java

package test.main;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

import test.mypac.DownloadThread;

public class Frame02 extends JFrame implements ActionListener{
   
   //생성자
   public Frame02() {
      setTitle("Frame02");
      setBounds(100, 100, 800, 500);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setLayout(new FlowLayout());
      
      JTextField inputText=new JTextField(10);
      add(inputText);
      
      JButton btn1=new JButton("눌러보셈");
      add(btn1);
      btn1.addActionListener(this);
      
      setVisible(true);
   }
   
   
   public static void main(String[] args) {
      new Frame02();
   }


   @Override
   public void actionPerformed(ActionEvent e) {
      System.out.println("버튼을 눌렀네요!");
      
    //새로운 스레드에서 다운로드 작업을 시킨다.
      new DownloadThread().start();
      
      System.out.println("actionPerformed() 메소드가 종료 됩니다.");
   }
   

   
}

Thread를 상속받은 스레드 클래스를 만들어 준 후 main에서 .start()를 사용하여 실행시켜줍니다.


 

스레드 클래스를 사용하지않고 main() 내에서 바로 사용할 수도 있습니다.

package test.main;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

import test.mypac.DownloadThread;

public class Frame05 extends JFrame implements ActionListener{
   
   //생성자
   public Frame05() {
      setTitle("Frame05");
      setBounds(100, 100, 800, 500);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setLayout(new FlowLayout());
      
      JTextField inputText=new JTextField(10);
      add(inputText);
      
      JButton btn1=new JButton("눌러보셈");
      add(btn1);
      btn1.addActionListener(this);
      
      setVisible(true);
   }
   
   
   public static void main(String[] args) {
      new Frame05();
   }


   @Override
   public  void  actionPerformed(ActionEvent e) {
      System.out.println("버튼을 눌렀네요!");
      //익명의 내부 클래스를 이용해서 객체 생성후 새로운 작업단위를 시작한다. 
      
      new Thread() {
         @Override
         public void run() {
            //완료하는데 10초가 걸리는 작업을 한다고 가정하자
            try {
               Thread.sleep(10000);
               System.out.println("다운로드가 완료 되었습니다");
            } catch (InterruptedException e1) {
               e1.printStackTrace();
            }
         }
      }.start();
      
      System.out.println("actionPerformed() 메소드가 종료 됩니다.");
   }
   
}

new Thread를 사용하여 익명의 내부 클래스를 이용해서 객체 생성을 하였습니다.

 


2. Runnable 인터페이스 사용

 

CountRunnable.java

package test.mypac;
/*
 *  새로운 스레드 만드는 방법2
 *  
 *  1. Runnable 인터페이스를 구현한 클래스를 정의한다.
 *  2. run() 메소드를 강제 오버라이드 한다.
 *  3. Thread 클래스로 객체를 생성하면서 해당클래스로 만든 객체를 생성자의 인자로 전달한다.
 *  4. Thread 클래스로 만든 객체의 start() 메소드를 호출해서 스레드를 시작 시킨다.
 */
public class CountRunnable implements Runnable{

   @Override
   public void run() {
      int count=0;
      while(true) {
         try {
            Thread.sleep(1000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
         count++; //카운트를 증가 시킨다.
         System.out.println("현재 카운트:"+count);
         if(count==10) break;// 카운트가 10이 되면 반복문 탈출 => run()메소드종료  => 스레드 종료를 의미 
      }
   }

}

Runnable 인터페이스를 사용한 방법입니다. run을 오버라이드해주었습니다.

 

package test.main;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

import test.mypac.CountRunnable;
import test.mypac.DownloadThread;

public class Frame06 extends JFrame implements ActionListener{
   
   //생성자
   public Frame06() {
      setTitle("Frame06");
      setBounds(100, 100, 800, 500);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setLayout(new FlowLayout());
      
      JTextField inputText=new JTextField(10);
      add(inputText);
      
      JButton btn1=new JButton("눌러보셈");
      add(btn1);
      btn1.addActionListener(this);
      
      setVisible(true);
   }
   
   
   public static void main(String[] args) {
      new Frame06();
   }


   @Override
   public  void  actionPerformed(ActionEvent e) {
      System.out.println("버튼을 눌렀네요!");
      
      Thread t=new Thread(new CountRunnable());
      t.start();
      
      System.out.println("actionPerformed() 메소드가 종료 됩니다.");
   }
   
}

main 에서 start를 시켜주었습니다.


Thread와 마찬가지로 Runnable 클래스를 따로 만들지 않고 바로 main에서 사용할 수 도 있습니다.

package test.main;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

import test.mypac.CountRunnable;
import test.mypac.DownloadThread;

public class Frame08 extends JFrame implements ActionListener{
   
   //생성자
   public Frame08() {
      setTitle("Frame06");
      setBounds(100, 100, 800, 500);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setLayout(new FlowLayout());
      
      JTextField inputText=new JTextField(10);
      add(inputText);
      
      JButton btn1=new JButton("눌러보셈");
      add(btn1);
      btn1.addActionListener(this);
      
      setVisible(true);
   }
   
   
   public static void main(String[] args) {
      new Frame08();
   }


   @Override
   public  void  actionPerformed(ActionEvent e) {
      System.out.println("버튼을 눌렀네요!");
      
      new Thread(new Runnable() {
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
		      int count=0;
		      while(true) {
		         try {
		            Thread.sleep(1000);
		         } catch (InterruptedException e) {
		            e.printStackTrace();
		         }
		         count++; //카운트를 증가 시킨다.
		         System.out.println("현재 카운트:"+count);
		         if(count==10) break;// 카운트가 10이 되면 반복문 탈출 => run()메소드종료  => 스레드 종료를 의미 
		      }
		}
      }).start();
      
      
      System.out.println("actionPerformed() 메소드가 종료 됩니다.");
   }
   
}

람다 함수를 사용해서도 만들 수 있습니다.

package test.main;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

import test.mypac.CountRunnable;
import test.mypac.DownloadThread;

public class Frame09 extends JFrame implements ActionListener{
   
   //생성자
   public Frame09() {
      setTitle("Frame06");
      setBounds(100, 100, 800, 500);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setLayout(new FlowLayout());
      
      JTextField inputText=new JTextField(10);
      add(inputText);
      
      JButton btn1=new JButton("눌러보셈");
      add(btn1);
      btn1.addActionListener(this);
      
      setVisible(true);
   }
   
   
   public static void main(String[] args) {
      new Frame09();
   }


   @Override
   public  void  actionPerformed(ActionEvent e) {
      System.out.println("버튼을 눌렀네요!");
      
      new Thread(()->{
    	  int count=0;
    	  while(true) {
		         try {
		            Thread.sleep(1000);
		         } catch (InterruptedException e2) {
		            e2.printStackTrace();
		         }
		         count++; //카운트를 증가 시킨다.
		         System.out.println("현재 카운트:"+count);
		         if(count==10) break;// 카운트가 10이 되면 반복문 탈출 => run()메소드종료  => 스레드 종료를 의미 
		      }
      }).start();
      
      
      System.out.println("actionPerformed() 메소드가 종료 됩니다.");
   }
   
}
반응형
Comments