2016-06-02 1 views
-1

질문이 불분명하면 죄송합니다.Runnable를 구현할 때 run()의이 참조가 Thread 객체를 참조 할 수 있습니까?

주 스레드를 제외한 모든 스레드를 저장하는 링크 된 목록이있는 간단한 다중 스레드 프로그램을 만들고 있습니다. 그런 다음 주 스레드를 종료하기 위해 신호를 보내길 원하지만 모든 다른 스레드가 닫힌 경우에만 스레드를 닫을 때 연결 목록에서 자체를 제거한 다음 주 스레드가 해당 목록을 검사하는지 확인합니다 이 null 경우 Shutdown_Handler.shutdown == true를 주는 대화 목록을 확인할 때 크기 == null 또는하지

여기 내 코드

public class MainProgram { 
    //some global static variable 
    static List<Thread> threadList = new LinkedList<Thread>(); 
    public void main() throws IOException { 
     ServerSocket serverSocket; 
     serverSocket = new ServerSocket(1234); 
     while(true){ 
      if(Shutdown_Handler.shutdown==true){ 
       //wait for all other thread close/terminate 
       return 
      } 
      Socket s = serverSocket.accept(); 
      ClientThread x = new ClientThread(s); 
      Thread y = new Thread(x); 
      threadList.add(y); 
      y.start(); 

     } 
    } 
} 

입니다. 문제는 목록에서 스레드 자체를 제거하는 방법을 모르겠다는 것입니다. 내가 검색 한 내용으로, 정상 개체에 대해, 나는, 그러나이

public class someObject { 
    public static void delete(){ 
     if(list.size = null) return; 
     list.remove(this); 
    } 
} 

같은 방법을 만들 수 있습니다 스레드의 경우, 클래스 Runnable 그래서 this 참조 객체이다하지만 스레드 목록

에 저장 구현
+0

정확하게 이해하면 Java에서 사용할 수있는 Futures와 함께 ExecutorService를 사용할 수 있습니다. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html – Mamun

+0

여러 스레드에서 목록을 조작하려면 Collections.synchronizedList (..) 또는 무언가를 사용하여 스레드로부터 안전하게 만들어야합니다. – waltersu

+0

정적 방법에서는 * this *를 참조 할 수 없습니다. Runnable 클래스에 현재의 thread를 얻으려면, Thread.currentThread()를 사용합니다. – waltersu

답변

1

List 대신 HashMap을 사용하는 것이 좋습니다. 키는 스레드 이름 (예 : Thread.getName()) 일 수 있으며 값은 스레드가됩니다. (Collections.synchronizedMap(...) 사용)

Map<String, Thread> threadMap = new HashMap<String, Thread>(); 

또한 synchronizedMap로이지도를 작성해야합니다

이제
Map<String, Thread> synchronizedMap = Collections.synchronizedMap(threadMap); 

당신이 스레드를 생성 할 때마다, 당신은 생성자에이의 HashMap를 전달하고 스레드에 대한 참조를 저장할 수 그것. 따라서 스레드가 종료 될 때 자신의 스레드 이름을 제거 할 키로 사용하여 HashMap에서 자신을 제거 할 수 있습니다. ClientThread가의 Runnable이라고 가정

1

, 기본 코드는 다음과 같습니다

public class ClientThread implements Runnable { 
    public void run() { 
     // do stuff 
     MainProgram.threadList.remove(Thread.currentThread()); 
    } 
} 

그러나이 문제의 몇 가지가 있습니다

목록에서 작업을 수행하는 다중 스레드있을거야
  1. 적절한 동기화없이. 이는 잘못된 것이며, 그렇게하면 간헐적 인 실패가 발생할 수 있습니다.

  2. finally 블록의 목록에서 스레드를 제거하지 않으면 비정상적으로 종료되는 스레드가 제거되지 않을 수 있습니다.

  3. 전역 정적을 사용하는 것은 좋지 않습니다. 그리고 더 나쁜 디자인은 맨손 (비공개) 변수로 노출됩니다.

  4. HashSet<Thread>은 스레드 수가 많으면 더 효율적입니다.

관련 문제