ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Thread] Thread, ThreadGroup
    java/Thread 2021. 5. 27. 20:38

    10페이지 분량의 글을 나름 열심히 정리했지만 헷갈리는 것이 있고 독자로 하여금 포스팅 이해가 지맘대로 일 것 같아서  싹다 새로 정리하여 글을 남긴다. 아오!!!!쭈바

     

    스레드 그룹은 서로 관련된 스레드를 그룹으로 다루기 위한 것이다.

    스레드 그룹에는 스레드 뿐만 아니라 스레드 그룹도 포함시킬 수 있다.

    보안상의 이유로 도입된 개념으로, 자신이 속한 스레드 그룹이나 하위 스레드 그룹은 변경할 수 있지만 다른 스레드 그룹의 스레드를 변경할 수는 없다. 

    public
    class ThreadGroup implements Thread.UncaughtExceptionHandler {
        private final ThreadGroup parent;
        String name; //스레드 그룹의 이름
        int maxPriority; //나중에 만들어질 스레드,스레드 그룹에 대해 우선순위의 최대값을 제한시킴
        boolean destroyed;
        boolean daemon;
    
        int nUnstartedThreads = 0;
        int nthreads;
        Thread threads[]; //스레드 그룹안에 포함될 스레드들
    
        int ngroups;
        ThreadGroup groups[]; //스레드 그룹안에 포함될 스레드 그룹들

     

    main메서드가 실행되는 스레드는 main스레드이다. main스레드는 main스레드 그룹에 포함되어있다.

    최상위 스레드 그룹은 system스레드 그룹이고 그 안에 main스레드 그룹이 담겨있다. main스레드 그룹안에서 main스레드가 실행되고 main메서드가 포함된 스레드가 바로 main스레드이다.

     

    system스레드 그룹 - main스레드 그룹 - main스레드 의 형태로 이루어져있다.

    system스레드 그룹은 main스레드 그룹의 부모이고, main스레드 그룹은 main스레드의 부모이다.

    그림으로 표현하면 간단하다.

     

    부모                                ->                   자식                       ->                             자식의 자식

    스레드 그룹
    system
    여러 스레드들
    Finalizer(가비지 컬렉션)등등....
    스레드 그룹
    main


    스레드
    main

    ThreadGroup의 list()메서드는 스레드 그룹에 포함된 스레드 그룹들, 활성상태의 스레드들을 list로 출력해준다. 
    하위 스레드 그룹은 또 그 스레드 그룹이 포함하고 있는 활성 스레드, 스레드 그룹들을 모두 출력해준다.
    스레드는 활성 스레드만 출력한다.!!!!!!!!
    new 상태에의 스레드들은 출력되지 않는다. 이것 때문에 두시간 동안 삽질했다ㅡㅡ

    ThreadGroup의 getParent()메서드는 이 스레드 그룹의 부모 스레드 그룹을 반환한다.

    Thread의 static메서드 currentThread()는 현재 코드가 실행중인 스레드를 반환한다.

    Thread의 인스턴스 메서드 getThreadGroup()은 스레드참조변수가 속해있는 스레드 그룹을 반환한다. 


     

    ThreadGroup의 list()메서드 테스트

    package threadTest;
    
    public class ThreadGroupMethodList {
    
    	public static void main(String[] args) {
    		Thread mainThread = Thread.currentThread(); 
    		//현재 돌아가고 있는 스레드는 메인스레드이므로 편의상 mainThread참조변수를 사용하였다.
    		
    		ThreadGroup mainThreadGroup = mainThread.getThreadGroup(); 
    		//메인스레드가 포함된 스레드 그룹은 메인 스레드 그룹이므로 mainThreadGroup으로 하였다.
    		
    		// ThreadGroup mainThreadGroup =Thread.currentThread().getThreadGroup(); 
    		// 한줄로 줄일수 있다.
    
    		mainThreadGroup.list();
    	}
    }
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]

    main스레드 그룹이 포함하고 있는 스레드들, 스레드 그룹들을 출력해준다.

    main스레드 하나와 스레드 그룹은 아무것도 포함하고 있지 않다.

     

    더나아가 main스레드 그룹의 부모 스레드 그룹을 참조하여 포함하고 있는 모든 스레드, 스레드 그룹들을 출력해보면

    package threadTest;
    
    public class ThreadGroupMethodList {
    
    	public static void main(String[] args) {
    		Thread mainThread = Thread.currentThread(); 
    		//현재 돌아가고 있는 스레드는 메인스레드이므로 편의상 mainThread참조변수를 사용하였다.
    		
    		ThreadGroup mainThreadGroup = mainThread.getThreadGroup(); 
    		//메인스레드가 포함된 스레드 그룹은 메인 스레드 그룹이므로 mainThreadGroup으로 하였다.
    		
    		// ThreadGroup mainThreadGroup =Thread.currentThread().getThreadGroup(); 
    		// 한줄로 줄일수 있다.
    
    		mainThreadGroup.list();
    		System.out.println();
    		
    		//추가된 코드
    		
    		ThreadGroup parent=mainThreadGroup.getParent();
    		parent.list();
    	}
    }
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
    
    java.lang.ThreadGroup[name=system,maxpri=10]
        Thread[Reference Handler,10,system]
        Thread[Finalizer,8,system]
        Thread[Signal Dispatcher,9,system]
        Thread[Attach Listener,5,system]
        java.lang.ThreadGroup[name=main,maxpri=10]
            Thread[main,5,main]
        java.lang.ThreadGroup[name=InnocuousThreadGroup,maxpri=10]
            Thread[Common-Cleaner,8,InnocuousThreadGroup]

    main스레드 그룹의 부모는 system스레드 그룹이라는 것을 확인 할 수 있다.

    또한 system스레드 그룹에는 main스레드 그룹만이 아닌 여러 스레드들과 다른 스레드 그룹을 포함하고 있음을 확인 할 수 있다.

     

    (추가내용) 삽질한 것 추가한다....

    package threadTest;
    
    public class ThreadGroupMethodList {
    
    	public static void main(String[] args) {
    		Thread mainThread = Thread.currentThread();
    		// 현재 돌아가고 있는 스레드는 메인스레드이므로 편의상 mainThread참조변수를 사용하였다.
    
    		ThreadGroup mainThreadGroup = mainThread.getThreadGroup();
    		// 메인스레드가 포함된 스레드 그룹은 메인 스레드 그룹이므로 mainThreadGroup으로 하였다.
    
    		// ThreadGroup mainThreadGroup =Thread.currentThread().getThreadGroup();
    		// 한줄로 줄일수 있다.
    
    		Thread mainThread2 = new Thread(new Runnable() {
    			public void run() {
    				try {
    					Thread.sleep(5000);
    				} catch (Exception e) {
    					// TODO: handle exception
    					e.printStackTrace();
    				}
    			}
    		}, "mainThread2");
    		//mainThread2.start(); 스레드 활성화 시키지 않으면 list에 출력되지 않는다.
    
    		mainThreadGroup.list();
    		System.out.println();
    	}
    }
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]

    mainThread2를 만들어 놓기만 하고 start()시키지 않으면 스레드그룹.list()에 mainThread2가 포함되어 있지 않다.

    이제 start()시켜보면

    package threadTest;
    
    public class ThreadGroupMethodList {
    
    	public static void main(String[] args) {
    		Thread mainThread = Thread.currentThread();
    		// 현재 돌아가고 있는 스레드는 메인스레드이므로 편의상 mainThread참조변수를 사용하였다.
    
    		ThreadGroup mainThreadGroup = mainThread.getThreadGroup();
    		// 메인스레드가 포함된 스레드 그룹은 메인 스레드 그룹이므로 mainThreadGroup으로 하였다.
    
    		// ThreadGroup mainThreadGroup =Thread.currentThread().getThreadGroup();
    		// 한줄로 줄일수 있다.
    
    		Thread mainThread2 = new Thread(new Runnable() {
    			public void run() {
    				try {
    					Thread.sleep(5000);
    				} catch (Exception e) {
    					// TODO: handle exception
    					e.printStackTrace();
    				}
    			}
    		}, "mainThread2");
    		mainThread2.start(); //start()시키면 list에 출력된다
    
    		mainThreadGroup.list();
    		System.out.println();
    
    	}
    }
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
        Thread[mainThread2,5,main]
    
    

    mainThread2가 추가되었다.


    ThreadGroup의 생성자

    스레드 그룹의 생성자는 두가지가 끝이다. 

    String name은 단순히 스레드 그룹의 이름을 지어주는 역할이다.

    두번째 생성자의 ThreadGroup parent가 있는데 지금 만들어질 스레드 그룹의 부모를 설정하는 것이다. 스레드 그룹이 어디 스레드 그룹에 붙을 것인지 보면된다.

     


    1. ThreadGroup(String name)

    new ThreadGroup(String name); 코드가 돌아가고 있는 Thread가 소속된 ThreadGroup이 부모가 된다. 

    이전의 Thread.currentThread(), threadGroup.getParent(), threadGroup.list(), threadGroup.getThreadGroup()의 메서드를 잘 기억하자.

     

    테스트

    package threadTest;
    
    public class ThreadGroupFirstConstructorTest1 {
    
    	public static void main(String[] args) {
    		ThreadGroup group=new ThreadGroup("테스트그룹");
    		//코드가 돌아가고 있는 main스레드가 포함된 스레드 그룹
    		//= main스레드 그룹
            //main스레드 그룹이 group의 부모 스레드 그룹이 됨
    		
            //맞는지 테스트해보자
            
    		ThreadGroup group2= group.getParent();
            //스레드 그룹의 getParent()메서드는 group의 부모 스레드 그룹을 리턴
    		group2.list();
            //group2가 포함하는 모든 스레드, 모든 스레드 그룹을 list형식으로 만들어 출력
    	}
    }

     

    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
        java.lang.ThreadGroup[name=테스트그룹,maxpri=10]

     

    현재 실행중인 main스레드가 포함된 main스레드 그룹이 이 스레드 그룹의 부모가 되었다.


     

    2. ThreadGroup(ThreadGroup parent, String name)

    생성자에 전달한 스레드 그룹 parent가 이 스레드 그룹의 부모가 된다.(즉 parent의 자식으로 생성된다)

    이 생성자에 ThreadGroup에 null이 들어가면 NPE를 던진다고 한다.

     

     

    테스트

    package threadTest;
    
    public class ThreadGroupFirstConstructorTest2 {
    
    	public static void main(String[] args) {
    		
    		ThreadGroup mainThreadGroup =Thread.currentThread().getThreadGroup(); 
    		ThreadGroup group = new ThreadGroup(mainThreadGroup, "main이 부모가 되는 스레드 그룹 group");
    		ThreadGroup subGroup= new ThreadGroup(group,"group이 부모가 되는 스레드 그룹 subGroup");
    		mainThreadGroup.list();
    	}
    }
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
        java.lang.ThreadGroup[name=main이 부모가 되는 스레드 그룹 group,maxpri=10]
            java.lang.ThreadGroup[name=group이 부모가 되는 스레드 그룹 subGroup,maxpri=10]
    

     

    ThreadGroup.getName()- 생성자에 전달한 name을 반환한다.

    public class ThreadGroupFirstConstructorTest2 {
    
    	public static void main(String[] args) {
    		
    		ThreadGroup mainThreadGroup =Thread.currentThread().getThreadGroup(); 
    		System.out.println(mainThreadGroup.getName());
    		ThreadGroup group=new ThreadGroup("test");
    		System.out.println(group.getName());
    		
    	}
    }
    
    main
    test
    

     


    Thread  클래스

     

    스레드참조변수.getName() - 스레드의 이름을 리턴

     

    스레드의 생성자에 String이 포함된 생성자들이 있는데 이름을 설정하지 않으면 스레드에서 자동으로 이름을 만들어 준다.

    Thread.class의 생성자들 중 String인자가 없는 생성자 몇개
    
    //nextThreadNum()메서드가 이름을 자동으로 만들어 준다.
    
    public Thread() {
            this(null, null, "Thread-" + nextThreadNum(), 0);
        }
        
    //스레드 이름을 넣지 않은 생성자 2
    public Thread(Runnable target) {
            this(null, target, "Thread-" + nextThreadNum(), 0);
        }
        
    //nextThreadNum() static메서드
        private static int threadInitNumber; //초기값 0(멤버 변수)
        
        //static메서드로 생성자에 이름 설정이 없으면 0부터 이름 자동 생성해줌
        private static synchronized int nextThreadNum() {
            return threadInitNumber++;
        }

    스레드의 우선순위는 1~10의 값을 가질 수 있다.

     

    스레드의 우선순위가 높을수록 더 많이 실행될 수 있는 기회를 가진다.

    MAX_PRIORITY는 10 

    MIN_PRIORITY는 1

    NORM_PRIORITY는 5

     

    setPriority(1~10의 값 or 위의 세개의 상수도 넣을수있다);

     

    그런데 ThreadGroup에도 int maxPriority; 가 있고 이를 설정하는 setMaxPriority()메서드, 이를 얻어오는 getMaxPriority()메서드가 있다. ThreadGroup의 maxPriority와 Thread의 priority는 어떠한 차이가 있는 것일까?

     

    설명이 복잡할 것 같아서 특정한 하나의 값을 정해서 설명하겠다.

    ThreadGroup의 setMaxPriority(4)로 maxPriority필드를 설정하면 maxPriority는 4가된다.

    이후에 이 스레드그룹에 포함시킬 스레드그룹의 maxPriority는 4초과 값인 setMaxPriority(5,6,7,8,9,10)를 설정해도 4가 설정된다. 

    스레드그룹에 앞으로 포함시킬 스레드의 경우도 마찬가지로 setPriority(5,6,7,8,9,10) 4초과 값을 설정해도 4로 설정된다.

     

    그러나 이전에 이미 만들어져있던 스레드는 우선순위가 변경되지 않는다. 

    main스레드 그룹에 우선순위가 10인 스레드를 만들고 그 이후에 main스레드 그룹의 setMaxPriority를 4로 바꾸면 setMaxPriority이전에 생성되어있는 스레드의 우선순위는 변하지 않는다. 

    setMaxPriority이전에 포함되어있던 MaxPriority가 4초과였던 스레드 그룹의 경우에는 어떻게 될까? 스레드와 다르게 스레드 그룹은 setMaxPriority가 4가 되면 이놈들도 4의 값으로 바뀌어버린다.

     

    테스트1. 스레드 그룹, 스레드가 먼저 추가되고 나중에 부모 스레드 그룹 maxPriority를 낮춘 경우

    1-1 //스레드 그룹, 스레드 우선순위 지정후 부모 스레드그룹 우선순위를 바꾼 경우 (+스레드.start()를 나중에 시킨경우)

    package threadTest;
    
    public class ThreadGroupMaxPriorityTest1 {
    
    	public static void main(String[] args) {
    		// 프로그램이 실행되고
    		// main스레드 그룹의 maxPriority는 기본 값 10이다.
    		// main스레드 그룹의 main스레드의 스레드 우선순위 기본 값은 5이다.
    
    		Runnable r = new Runnable() {
    			public void run() {
    				try {
    					Thread.sleep(5000);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		};
    		
    		Thread main = Thread.currentThread();
    		ThreadGroup mainGroup = main.getThreadGroup();
    		mainGroup.list();
    		System.out.println();
    
    		ThreadGroup group1 = new ThreadGroup(mainGroup, "group1");
    		System.out.println("부모가 main스레드 그룹인 스레드 그룹 group1 생성");
    		Thread mainThread2 = new Thread(mainGroup, r, "mainThread2");
    		//mainThread2.start(); 
    		System.out.println("부모가 main스레드 그룹인  mainThread2 생성 ");
    
    		System.out.println();
    		mainGroup.list();
    		System.out.println();
    
    		mainGroup.setMaxPriority(3);  //스레드 그룹, 스레드 우선순위 지정후 부모 스레드그룹 우선순위를 바꾼 경우
    		System.out.println("main스레드 그룹의 우선순위 제한 값 3로 변경");
    		System.out.println("이 상태에서 mainThread2를 start()시키면");
    		System.out.println();
    		mainThread2.start();
    		mainGroup.list();
    		System.out.println();
    		System.out.println("스레드를 setMaxPriority(3)이후에 start()시킨경우 우선순위는 5로 변함이 없다.");
    		System.out.println("하위 스레드그룹의 MaxPriority는 10에서 3으로 변경이 되었다.");
    	}
    }
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
    
    부모가 main스레드 그룹인 스레드 그룹 group1 생성
    부모가 main스레드 그룹인  mainThread2 생성 
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
        java.lang.ThreadGroup[name=group1,maxpri=10]
    
    main스레드 그룹의 우선순위 제한 값 3로 변경
    이 상태에서 mainThread2를 start()시키면
    
    java.lang.ThreadGroup[name=main,maxpri=3]
        Thread[main,5,main]
        Thread[mainThread2,5,main]
        java.lang.ThreadGroup[name=group1,maxpri=3]
    
    스레드를 setMaxPriority(3)이후에 start()시킨경우 우선순위는 5로 변함이 없다.
    하위 스레드그룹의 MaxPriority는 10에서 3으로 변경이 되었다.
    

     

    1-2  //스레드 그룹, 스레드 우선순위 지정후 부모 스레드그룹 우선순위를 바꾼 경우 (+스레드.start()를 먼저 시킨경우)

    package threadTest;
    
    public class ThreadGroupMaxPriorityTest1 {
    
    	public static void main(String[] args) {
    		// 프로그램이 실행되고
    		// main스레드 그룹의 maxPriority는 기본 값 10이다.
    		// main스레드 그룹의 main스레드의 스레드 우선순위 기본 값은 5이다.
    
    		Runnable r = new Runnable() {
    			public void run() {
    				try {
    					Thread.sleep(5000);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		};
    		
    		Thread main = Thread.currentThread();
    		ThreadGroup mainGroup = main.getThreadGroup();
    		mainGroup.list();
    		System.out.println();
    
    		ThreadGroup group1 = new ThreadGroup(mainGroup, "group1");
    		System.out.println("부모가 main스레드 그룹인 스레드 그룹 group1 생성");
    		Thread mainThread2 = new Thread(mainGroup, r, "mainThread2");
    		mainThread2.start(); 
    		System.out.println("이 상태에서 mainThread2를 start()");
    		System.out.println("부모가 main스레드 그룹인  mainThread2 생성 ");
    
    		System.out.println();
    		mainGroup.list();
    		System.out.println();
    
    		mainGroup.setMaxPriority(3);  //스레드 그룹, 스레드 우선순위 지정후 부모 스레드그룹 우선순위를 바꾼 경우
    		System.out.println("main스레드 그룹의 우선순위 제한 값 3로 변경");
    		System.out.println();
    		//mainThread2.start();
    		mainGroup.list();
    		System.out.println();
    		System.out.println("스레드를 setMaxPriority(3)이전에 start()시킨경우도 우선순위는 5로 변함이 없다.");
    		System.out.println("하위 스레드그룹의 MaxPriority는 10에서 3으로 변경이 되었다.");
    	}
    }

     

    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
    
    부모가 main스레드 그룹인 스레드 그룹 group1 생성
    이 상태에서 mainThread2를 start()
    부모가 main스레드 그룹인  mainThread2 생성 
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
        Thread[mainThread2,5,main]
        java.lang.ThreadGroup[name=group1,maxpri=10]
    
    main스레드 그룹의 우선순위 제한 값 3로 변경
    
    java.lang.ThreadGroup[name=main,maxpri=3]
        Thread[main,5,main]
        Thread[mainThread2,5,main]
        java.lang.ThreadGroup[name=group1,maxpri=3]
    
    스레드를 setMaxPriority(3)이전에 start()시킨경우도 우선순위는 5로 변함이 없다.
    하위 스레드그룹의 MaxPriority는 10에서 3으로 변경이 되었다.
    

     

     스레드,스레드 그룹이 먼저 추가 되어있으면 스레드는 변경안됨, 스레드 그룹은 변경됨

     

    테스트2. 

    package threadTest;
    
    public class ThreadGroupMaxPriorityTest1 {
    
    	public static void main(String[] args) {
    		// 프로그램이 실행되고
    		// main스레드 그룹의 maxPriority는 기본 값 10이다.
    		// main스레드 그룹의 main스레드의 스레드 우선순위 기본 값은 5이다.
    
    		Runnable r = new Runnable() {
    			public void run() {
    				try {
    					Thread.sleep(5000);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		};
    		
    		Thread main = Thread.currentThread();
    		ThreadGroup mainGroup = main.getThreadGroup();
    		mainGroup.list();
    		System.out.println();
    		
    		mainGroup.setMaxPriority(3);  //스레드 그룹, 스레드 우선순위 지정후 부모 스레드그룹 우선순위를 바꾼 경우
    		System.out.println("main스레드 그룹의 우선순위 제한 값 3로 변경");
    		System.out.println();
    		mainGroup.list();
    		System.out.println();
    		
    		ThreadGroup group1 = new ThreadGroup(mainGroup, "group1");
    		System.out.println("부모가 main스레드 그룹인 스레드 그룹 group1 생성");
    		Thread mainThread2 = new Thread(mainGroup, r, "mainThread2");
    		System.out.println("부모가 main스레드 그룹인  mainThread2 생성 ");
    		mainThread2.start(); 
    		System.out.println("이 상태에서 mainThread2를 start()");
    		mainGroup.list();
    		System.out.println();		
    
    		System.out.println();
    		System.out.println("스레드를 setMaxPriority(3)이후에 start()시킨경우 우선순위는 5로 변함이 없다.");
    		System.out.println("하위 스레드그룹의 MaxPriority는 10에서 3으로 변경이 되었다.");
    	}
    }
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
    
    main스레드 그룹의 우선순위 제한 값 3로 변경
    
    java.lang.ThreadGroup[name=main,maxpri=3]
        Thread[main,5,main]
    
    부모가 main스레드 그룹인 스레드 그룹 group1 생성
    부모가 main스레드 그룹인  mainThread2 생성 
    이 상태에서 mainThread2를 start()
    java.lang.ThreadGroup[name=main,maxpri=3]
        Thread[main,5,main]
        Thread[mainThread2,3,main]
        java.lang.ThreadGroup[name=group1,maxpri=3]
    
    
    스레드를 setMaxPriority(3)이후에 start()시킨경우 우선순위는 5로 변함이 없다.
    하위 스레드그룹의 MaxPriority는 10에서 3으로 변경이 되었다.

    main스레드 그룹의 우선순위를 3으로 바꾸고 group1을 추가시키면 3으로 설정된다.

    이미 실행중인 main스레드의 우선순위는 5로 변함이 없다. 새로 만든 mainThread2는 변경된 main스레드 그룹 우선순위3을 가지면서 생성된다.

     

    테스트3.  초과값을 설정한 경우

    package threadTest;
    
    public class ThreadGroupMaxPriorityTest1 {
    
    	public static void main(String[] args) {
    		// 프로그램이 실행되고
    		// main스레드 그룹의 maxPriority는 기본 값 10이다.
    		// main스레드 그룹의 main스레드의 스레드 우선순위 기본 값은 5이다.
    
    		Runnable r = new Runnable() {
    			public void run() {
    				try {
    					Thread.sleep(5000);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		};
    		Thread main=Thread.currentThread();
    		ThreadGroup mainGroup=main.getThreadGroup();
    		mainGroup.list(); //초기
    		System.out.println();
    		
    		mainGroup.setMaxPriority(3); //부모 스레드 그룹 우선순위 변경
    		mainGroup.list();
    		System.out.println("main스레드는 setPriority명시적 설정안하면 그대로 ");
    		System.out.println();
    		
    		main.setPriority(10); 
    		mainGroup.list();
    		System.out.println("부모 스레드 그룹의 변경된 최대허용 3이 max라 10으로 설정해도 3으로 설정됨");
    	}
    }
    
    java.lang.ThreadGroup[name=main,maxpri=10]
        Thread[main,5,main]
    
    java.lang.ThreadGroup[name=main,maxpri=3]
        Thread[main,5,main]
    main스레드는 setPriority명시적 설정안하면 그대로 
    
    java.lang.ThreadGroup[name=main,maxpri=3]
        Thread[main,3,main]
    부모 스레드 그룹의 변경된 최대허용 3이 max라 10으로 설정해도 3으로 설정됨

     

     

     


    여기서부터는 ......정리 하기전에 써놓은 내용들...그냥 남겨놓는다. 나중에 심심할때 정리해야겠다 아아....

    package threadTest;
    
    public class ThreadImplementation {
    	public static void main(String[] args) {
    		Thread th = new Thread(new ImpleRunnable(), "test thread"); //스레드 이름 명시함
    		th.start();
    
    		try {
    			Thread.sleep(2000);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		Thread th2 = new Thread(new ImpleRunnable()); //스레드 이름 명시x
    		th2.setPriority(7);
    		th2.start();
    		
    		try {
    			Thread.sleep(2000);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		Thread th3 = new Thread(new ImpleRunnable()); //스레드 이름 명시x
    		th3.start();
    	}
    }
    
    class ImpleRunnable implements Runnable {
    	public void run() {
    		Thread thread = Thread.currentThread(); // 현재 코드가 돌아가고 있는 스레드를 가져옴
    		ThreadGroup group = thread.getThreadGroup(); // 스레드 thread가 속한 스레드그룹
    
    		System.out.println("thread.getId(): " + thread.getId()); //스레드의 id(name이 아님)
    		System.out.println("thread.getName(): " + thread.getName()); //스레드의 이름
    		System.out.println("thread.getpriotity(): " + thread.getPriority()); //스레드의 우선순위
    		System.out.println("thread.getState(): " + thread.getState()); //스레드의 현재 상태
    		System.out.println("group.getName(): " + group.getName()); //스레드그룹 이름
    		System.out.println("group.isDaemon(): " + group.isDaemon()); //스레드그룹이 데몬스레드그룹인지
    		System.out.println("group.getMaxPriority(): " + group.getMaxPriority()); 
            //스레드그룹에 포함된 스레드, 스레드 그룹이 가질 수 있는 최대 우선순위
    		System.out.println("group.toString(): " + group.toString());
    		System.out.println();
    	}
    }

    결과

    thread.getId(): 12 //스레드 번호
    thread.getName(): test thread //생성자에 설정한 이름이 출력됨
    thread.getpriotity(): 5 //main스레드의 우선순위인 5를 상속받는다.
    thread.getState(): RUNNABLE
    group.getName(): main //main스레드에서 이 스레드를 생성했으므로 main스레드가 속한 main스레드그룹으로 속하게 된다.
    group.isDaemon(): false
    group.getMaxPriority(): 10 //main스레드 그룹에 포함된 스레드,스레드 그룹들의 허용 우선순위
    group.toString(): java.lang.ThreadGroup[name=main,maxpri=10]
    
    thread.getId(): 13 //스레드 번호
    thread.getName(): Thread-0 //이름이 지어진 익명 스레드
    thread.getpriotity(): 7 //setPriority(7)로 설정해서 스레드의 우선순위가 7로 변경된다.
    thread.getState(): RUNNABLE
    group.getName(): main
    group.isDaemon(): false
    group.getMaxPriority(): 10
    group.toString(): java.lang.ThreadGroup[name=main,maxpri=10]
    
    thread.getId(): 14 //스레드 번호
    thread.getName(): Thread-1 //이름이 지어진 익명 스레드
    thread.getpriotity(): 5
    thread.getState(): RUNNABLE
    group.getName(): main
    group.isDaemon(): false
    group.getMaxPriority(): 10
    group.toString(): java.lang.ThreadGroup[name=main,maxpri=10]
    
    

     


    우선순위 속성 테스트

    public class ThreadImplementation {
    	public static void main(String[] args) {	
    		//main스레드 그룹의 main스레드의 우선순위는 기본으로 5로 설정됨
    		Thread th = new Thread(new ImpleRunnable());
    		th.start(); //생성된 스레드는 main스레드의 우선순위를 상속받아 5가 출력될 것임
    		
    		try {
    			Thread.sleep(2000);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		Thread.currentThread().setPriority(7); //메인스레드의 우선순위를 7로 변경
    		
    		Thread th2 = new Thread(new ImpleRunnable());
    		th2.start(); //생성된 스레드는 main스레드의 우선순위를 상속받아 7이 출력될 것임
    		
    		
    	}
    }
    
    class ImpleRunnable implements Runnable {
    	public void run() {
    		Thread thread = Thread.currentThread(); // 현재 코드가 돌아가고 있는 스레드를 가져옴
    		ThreadGroup group = thread.getThreadGroup(); // 스레드가 속한 스레드그룹
    
    		System.out.println("thread.getId(): " + thread.getId());
    		System.out.println("thread.getName(): " + thread.getName());
    		System.out.println("thread.getpriotity(): " + thread.getPriority());
    		System.out.println("group.getName(): " + group.getName());
    		System.out.println("group.getMaxPriority(): " + group.getMaxPriority());
    		System.out.println();
    	}
    }

    결과

    thread.getId(): 12
    thread.getName(): Thread-0
    thread.getpriotity(): 5
    group.getName(): main
    group.getMaxPriority(): 10

    thread.getId(): 13
    thread.getName(): Thread-1
    thread.getpriotity(): 7
    group.getName(): main
    group.getMaxPriority(): 10


    스레드 그룹의 maxPriority테스트

     

    참고

    Thread.class의 setPriority()메서드 구조
    
    public final void setPriority(int newPriority) {
            ThreadGroup g;
            checkAccess();
            if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { //1~10사이의 값이 아니면 예외 던짐
                throw new IllegalArgumentException();
            }
            if((g = getThreadGroup()) != null) {
            //우선순위를 자기가 포함된 스레드 그룹에 설정된 우선순위보다 높게 설정해도
            //스레드 그룹의 최대값으로 설정됨
                if (newPriority > g.getMaxPriority()) { 
                    newPriority = g.getMaxPriority();
                }
                setPriority0(priority = newPriority);
            }
        }

     

    테스트

    public class ThreadImplementation {
    	public static void main(String[] args) {
    		ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
    		mainThreadGroup.setMaxPriority(6); 
            // 메인 스레드 그룹의 최대 우선순위를 6으로 변경 
            // 메인 스레드 그룹에 포함된 스레드들, 스레드 그룹등의 우선순위는 6을 넘을 수 없음
    
    		Thread th = new Thread(new ImpleRunnable());
    		th.setPriority(7); 
            //7로 설정하여도 main스레드 그룹의 최대 허용 우선순위가6으로 설정되어 6으로 설정됨
    		th.start();
    	}
    }
    
    class ImpleRunnable implements Runnable {
    	public void run() {
    		Thread thread = Thread.currentThread(); 
    		ThreadGroup group = thread.getThreadGroup(); 
    
    		System.out.println("thread.getId(): " + thread.getId());
    		System.out.println("thread.getName(): " + thread.getName());
    		System.out.println("thread.getpriotity(): " + thread.getPriority()); //6출력
            //코드9번줄에서 우선순위를 7로 설정했지만 메인스레드 최대 허용 우선순위가6으로 설정되어
            //있어 6으로 설정됨
    		System.out.println("group.getName(): " + group.getName());
    		System.out.println("group.getMaxPriority(): " + group.getMaxPriority());
    		System.out.println();
    	}
    }

     

    결과

    thread.getId(): 12
    thread.getName(): Thread-0
    thread.getpriotity(): 6
    group.getName(): main
    group.getMaxPriority(): 6

     

    같은 예제를 하나 더보자

    public class ThreadImplementation {
    	public static void main(String[] args) {
    		ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
    		mainThreadGroup.setMaxPriority(4); // 메인 스레드 그룹에 포함된 스레드의 최대 가능 우선순위를 4로 변경
    		
    		Thread.currentThread().setPriority(8); //메인 스레드의 우선순위를 8로 설정해도 4로 설정됨
    		
    		Thread th = new Thread(new ImpleRunnable()); //생성된 스레드는 메인 스레드의 우선순위인 4를 물려받음
    		th.start();
    	}
    }
    
    class ImpleRunnable implements Runnable {
    	public void run() {
    		Thread thread = Thread.currentThread(); // 현재 코드가 돌아가고 있는 스레드를 가져옴
    		ThreadGroup group = thread.getThreadGroup(); // 스레드가 속한 스레드그룹
    
    		System.out.println("thread.getId(): " + thread.getId());
    		System.out.println("thread.getName(): " + thread.getName());
    		System.out.println("thread.getpriotity(): " + thread.getPriority());
    		System.out.println("group.getName(): " + group.getName());
    		System.out.println("group.getMaxPriority(): " + group.getMaxPriority());
    		System.out.println();
    	}
    }

    결과

    thread.getId(): 12
    thread.getName(): Thread-0
    thread.getpriotity(): 4
    group.getName(): main
    group.getMaxPriority(): 4


    public class ThreadImplementation {
    	public static void main(String[] args) {
    		ThreadGroup main = Thread.currentThread().getThreadGroup();
    		
    		ThreadGroup group1 = new ThreadGroup("group1");
    		ThreadGroup group2 = new ThreadGroup("group2");
    		
    		ThreadGroup subgroup1 = new ThreadGroup(group1, "group1-subGroup1");
    		ThreadGroup subgroup2 = new ThreadGroup(group1, "group1-subGroup2");
    		
    		main.list();
    		
    	}
    }

    결과

    java.lang.ThreadGroup[name=main,maxpri=10] //main스레드 그룹
        Thread[main,5,main] //포함된 main스레드
        java.lang.ThreadGroup[name=group1,maxpri=10] //하위 스레드 그룹 group1
            java.lang.ThreadGroup[name=group1-subGroup1,maxpri=10] //group1의 하위 스레드 그룹 subGroup1
            java.lang.ThreadGroup[name=group1-subGroup2,maxpri=10] //group1의 하위 스레드 그룹 subGroup2
        java.lang.ThreadGroup[name=group2,maxpri=10] //하위 스레드 그룹 group2


    ThreadGroup의 getParent()메서드 부모 스레드 그룹 리턴

    ThreadGroup.class
     
    //생성자
    public ThreadGroup(String name) { 
    // 생성자에 이름만 넣어주는 경우 현재 스레드가 포함된 스레드 그룹이 만들어줄 스레드 그룹의 부모가 됨
            this(Thread.currentThread().getThreadGroup(), name);
    }
    
    //생성자에 스레드 그룹을 넣어주면 만들어질 스레드 그룹의 부모가 됨
    public ThreadGroup(ThreadGroup parent, String name) { //parent그룹의 하위에 이 스레드 그룹을 생성
            this(checkParentAccess(parent), parent, name);
    }
    
    private ThreadGroup(Void unused, ThreadGroup parent, String name) {
            this.name = name;
            this.maxPriority = parent.maxPriority; 
            //이 그룹의 maxPriority는 parent그룹의 maxPriority로 설정됨
            this.daemon = parent.daemon; 
            this.parent = parent; //이 그룹의 부모가 parent가 됨
            parent.add(this); //parent그룹에 이 그룹을 자식으로 추가한다.
    }
    
    

     

    테스트

    public class ThreadImplementation {
    	public static void main(String[] args) {
    		ThreadGroup main = Thread.currentThread().getThreadGroup();
    		ThreadGroup group1 = new ThreadGroup("group1");
    		// 현재 스레드(main)가 포함된 스레드그룹(main스레드 그룹)의 자식으로 스레드그룹(group1)이 만들어짐
    		// ThreadGroup group1=new ThreadGroup(main,"group1");과 같다.
    
    		ThreadGroup group2 = new ThreadGroup("group2");
    		
    		ThreadGroup subgroup1 = new ThreadGroup(group1, "subGroup1");
    		// 스레드 그룹 group1의 자식으로 스레드그룹 subgroup1이 생성됨
    
    		// ThreadGroup subgroup1=new ThreadGroup("subGroup1");으로 하면
    		// main스레드 그룹의 자식으로 스레드 그룹subGroup1이 생성된다.
    
    		ThreadGroup subgroup2 = new ThreadGroup(group1, "subGroup2");
    		// 스레드 그룹 group1의 자식으로 스레드그룹 subgroup2가 생성됨
    
    		System.out.println(group1.getParent().getName());
    		// group1의 부모 스레드 그룹= main스레드 그룹
    		
    		System.out.println(group2.getParent().getName());
    		// group1의 부모 스레드 그룹= main스레드 그룹
    
    		System.out.println(group1.getParent().getParent().getName());
    		// main스레드 그룹의 부모 스레드 그룹= system스레드 그룹
    		//= main.getParent().getName()와 같다.
    
    		System.out.println(subgroup1.getParent().getName());
    		// subgroup1의 부모 스레드 그룹= group1 스레드 그룹
    
    		System.out.println(subgroup2.getParent().getName());
    		// subgroup2의 부모 스레드 그룹= group1 스레드 그룹
    	}
    }

    부모-자식 관계

     

    스레드 그룹
    system
    스레드 여러개
    Finalizer(가비지 컬렉션)등등....
    스레드 그룹
    main
    스레드
    main
    스레드 그룹
    group1
    스레드 그룹
    subgroup1
    스레드 그룹
    subgroup2
    스레드 그룹
    group2

     

    결과

    main
    main
    system
    group1
    group1

     

    시뮬레이션1)

    main스레드 그룹의 최대 허용 우선순위는 기본 10이다 

    main스레드, group1스레드 그룹, group2스레드 그룹은 10까지 사용할 수 있다.

     

    이 상태에서 group1스레드 그룹의 최대 허용 우선순위를 5로 설정하면

    main스레드, group2스레드 그룹은 그대로 10까지 사용할 수 있고,  앞으로 스레드 그룹 group2에 속할 스레드,스레드 그룹들은 우선순위 5를 초과할 수 없다. 

     

    시뮬레이션2)

    main스레드 그룹의 최대 허용 우선순위를 4로 사용하면 

    main스레드, 다른 스레드 ,group1에 포함될 스레드,스레드그룹 , group2에 포함될 스레드, 스레드 그룹들은 4초과를 설정할 수 없다. 


    최상위 스레드 그룹과 최상위 스레드 그룹이 포함하고 있는 스레드 그룹, 스레드들을 출력해보자

    public class ThreadImplementation {
    	public static void main(String[] args) {
    
    		ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
    		ThreadGroup systemGroup = mainGroup.getParent();
    		
            //The top-level thread group is the only thread group whose parent is null.
    		if(systemGroup.getParent()==null) { 
    			System.out.println("systemGroup이 조상 스레드 그룹임");
    			System.out.println("하위 스레드 그룹, 스레드 출력");
    			systemGroup.list();
    		}else {
    			System.out.println("systemGroup의 부모 스레드 그룹이 존재");
    		}
    	}
    }

    결과

    systemGroup이 조상 스레드 그룹임
    하위 스레드 그룹, 스레드 출력
    java.lang.ThreadGroup[name=system,maxpri=10]
        Thread[Reference Handler,10,system]
        Thread[Finalizer,8,system]
        Thread[Signal Dispatcher,9,system]
        Thread[Attach Listener,5,system]
        java.lang.ThreadGroup[name=main,maxpri=10]
            Thread[main,5,main]
        java.lang.ThreadGroup[name=InnocuousThreadGroup,maxpri=10]
            Thread[Common-Cleaner,8,InnocuousThreadGroup]


    ThreadGroup의

    activeCount()메서드

    //스레드 그룹 하위에 있는 활성 상태인 스레드 총 개수를 반환

     

    Thread의

    static activeCount()메서드 

    //자신이 속한 스레드그룹의 activeCount()메서드와 같다.

    public class ThreadImplementation {
    	public static void main(String[] args) {
    		System.out.println(Thread.currentThread().getName() + "스레드 실행됨");
    
    		ThreadGroup main = Thread.currentThread().getThreadGroup();
    
    		ThreadGroup group1 = new ThreadGroup("group1");
    		ThreadGroup group2 = new ThreadGroup("group2");
    
    		// group1의 하위 스레드 그룹
    		ThreadGroup subgroup1 = new ThreadGroup(group1, "subGroup1");
    		ThreadGroup subgroup2 = new ThreadGroup(group1, "subGroup2");
    
    		// 5개의 스레드가 어디 속해 있는지 밑의 테이블 참조
    		Thread one = new Thread(main, new ImpleRunnable(), "main그룹에 포함된 main스레드2 ");
    		Thread two = new Thread(group1, new ImpleRunnable(), "group1에 포함된 스레드");
    		Thread three = new Thread(group2, new ImpleRunnable(), "group2에 포함된 스레드");
    		Thread four = new Thread(subgroup1, new ImpleRunnable(), "subGroup1에 포함된 스레드");
    		Thread five = new Thread(subgroup2, new ImpleRunnable(), "subGroup2에 포함된 스레드");
    
    		// 5개의 스레드를 시작시킨다.
    		one.start();
    		two.start();
    		three.start();
    		four.start();
    		five.start();
    
    		try {
    			Thread.sleep(500);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		System.out.println();
    		System.out.println("main스레드 그룹에서 실행되고 있는 총 스레드 개수: " + main.activeCount());
    		System.out.println();
    
    		System.out.println(Thread.currentThread().getName() + "스레드 종료됨");
    	}
    }
    
    class ImpleRunnable implements Runnable {
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + " 시작됨"); // 각 스레드 시작
    		try {
    			Thread.sleep(3000); 
                // 이 스레드에서 3초동안 정지 
                //main스레드에서 활성상태 개수 카운팅전 각스레드가 종료될 수 있기 때문
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		System.out.println(Thread.currentThread().getName() + " 종료됨"); // 각 스레드 종료
    	}
    }
    

    테이블

    다섯 개의 스레드가 어디에 속해 있나 확인하자.

    스레드 그룹
    system
    스레드 여러개
    Finalizer(가비지 컬렉션)등등.....
    스레드 그룹
    main
    스레드 main( main함수가 포함된)
    스레드 one
    스레드 그룹
    group1
    스레드 그룹
    subgroup1
    스레드 four
    스레드 그룹
    subgroup2
    스레드 five
    스레드 two
    스레드 그룹
    group2
    스레드 three

    결과

     

    main스레드 실행됨
    main그룹에 포함된 main스레드2  시작됨
    group1에 포함된 스레드 시작됨
    group2에 포함된 스레드 시작됨
    subGroup2에 포함된 스레드 시작됨
    subGroup1에 포함된 스레드 시작됨

    main스레드 그룹에서 실행되고 있는 총 스레드 개수: 6 

    //main메서드인 main스레드 + 스레드 one~five 다섯개

    //총6개의 스레드 활성화 

    main스레드 종료됨
    main그룹에 포함된 main스레드2  종료됨
    subGroup2에 포함된 스레드 종료됨
    subGroup1에 포함된 스레드 종료됨
    group1에 포함된 스레드 종료됨
    group2에 포함된 스레드 종료됨


    ThreadGroup의 activeGroupCount()

    //특정한 스레드 그룹의 하위에 존재하는 스레드 그룹을 깡그리 세어 총 개수 반환

     

    테스트가 애매까리 해서 스레드 그룹의 depth를 한단계 더 추가하였다.

    subgroup1의 하위 그룹으로 스레드 그룹 두개 childsub1, childsub2를 만들었다.

    스레드 그룹
    system
    스레드 여러개
    Finalizer(가비지 컬렉션 )등등.....
    스레드 그룹
    main
    스레드
    main
    스레드 그룹
    group1
    스레드 그룹
    subgroup1
    스레드 그룹
    childsub1
    스레드 그룹
    childsub2
    스레드 그룹
    subgroup2
    스레드 그룹
    group2
    public class ThreadImplementation {
    	public static void main(String[] args) {
    		System.out.println(Thread.currentThread().getName() + " 스레드 실행됨");
    
    		ThreadGroup main = Thread.currentThread().getThreadGroup();
    		
           		// main의 하위 스레드 그룹
    		ThreadGroup group1 = new ThreadGroup("group1");
    		ThreadGroup group2 = new ThreadGroup("group2");
    
    		// group1의 하위 스레드 그룹
    		ThreadGroup subgroup1 = new ThreadGroup(group1, "subgroup1");
    		ThreadGroup subgroup2 = new ThreadGroup(group1, "subgroup2");
    		
    		// subgroup1의 하위 스레드 그룹
    		ThreadGroup childsub1= new ThreadGroup(subgroup1,"childsub1");
    		ThreadGroup childsub2= new ThreadGroup(subgroup1,"childsub2");
    		
    		
    		System.out.println(main.activeGroupCount()); //6
    		//group1,group2,subgroup1,subgroup2,childsub1,childsub2 
            
    		System.out.println(group1.activeGroupCount()); //4
            	//subgroup1,subgroup2,childsub1,childsub2
            
    		System.out.println(group2.activeGroupCount()); //0
            	//하위 그룹에 존재하는 그룹이 없음
    		 
    		System.out.println(subgroup1.activeGroupCount()); //2
            	//childsub1,childsub2
            
    		System.out.println(subgroup2.activeGroupCount()); //0
            	//하위 그룹에 존재하는 그룹이 없음
    	}
    	
    }

     

    댓글

Designed by Tistory.