2014-07-08 2 views
1

Java의 여러 스레드간에 클래스 배열을 공유하려면 어떻게합니까? 나는 모두 입력 클래스의 배열을 공유하고 배열 (즉)의 요소를 인쇄하는 2 개 스레드를 원하는 이제Java의 여러 스레드간에 자원을 공유하려면 어떻게합니까?

public class Input { 
    int index; 
    int[] input = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 

    public Input(){ 
     index = 0; 
    } 

    public void print(int index){ 
     System.out.println(input[index]); 
    } 

    synchronized public int getIndex(){ 
     if(index == 15) 
      return -1; 
     return index++; 
    } 

} 

:

내가 다음과 같이 배열을 가진 클래스라는 입력을 말해봐 스레드는 함께 15 배 (배열의 요소 수) 인쇄해야합니다. 마지막으로

public class MyThread implements Runnable{ 

    Thread t; 
    int index; 
    Input ip; 

    public MyThread(Input ip, String name){ 
     t = new Thread(this, name); 
     this.ip = ip; 
     index = 0; 
     t.start(); 
    } 

    @Override 
    public void run() {  
     while((index=ip.getIndex())!=-1){ 
      System.out.println(t.getName()); 
      ip.print(index); 
     } 

    } 

} 

그리고, 스레드 설정하는 코드 :

public class Caller { 

    /** 
    * @param args 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException { 
     // TODO Auto-generated method stub 
     Input ip = new Input(); 
     MyThread t1 = new MyThread(ip, "Thread1"); 
     MyThread t2 = new MyThread(ip, "Thread2"); 
     t1.t.join(); 
     t2.t.join(); 

    } 

} 

출력은해야 뭔가 같은 :

Thread1

이 내 스레드 클래스입니다 ,363,210

Thread2

2

Thread2

3

Thread1

4

Thread2

5

01,235,

등이 배열의 마지막 요소에 도달 할 때까지 계속됩니다.

+0

그리고 귀하의 질문은 무엇입니까? – Krumia

+0

당신이 가지고있는 것은 괜찮을 것이지만 이것은 사소한 클래스이고 루프의 주요 부분에서 동기화 된 메서드를 사용하기 때문에 아마도 Thread1이 끝나기 전에 Thread1이 종료 될 것입니다. –

+0

오오 그렇습니다. 더 큰 어레이에서 작동하는 것 같습니다. 미안합니다. 하지만 출력 결과는 다음과 같습니다. Thread1 Thread2 2 1 Thread1 3 (스레드 이름이 여러 번 인쇄됩니다). 또한, 어떻게 잠을 자지 않고 교대로 만들 수 있습니까? – drunkenfist

답변

2

스레드가 Input.index에 대한 액세스를 동기화 했으므로 Input 클래스가 좋습니다. 귀하의 실제 문제는 MyThread.run입니다. 이 두 라인 :

System.out.println(t.getName()); 
    ip.print(index); 

메이크업 System.out.println-2 별도의 호출. 다중 스레드 컨텍스트에서는 스레드간에 인터리브되도록 바인딩되므로 결과물은 (전역) 순서를 벗어납니다.

2 개의 호출을 분리 할 수 ​​없도록하려면이 2 개의 호출을 "원자"(일종의 동기화 블록)로 정렬해야합니다. 이 코드 블록에 대한 액세스를 보호하고 상호 실행을 독점적으로 만들려면 스레드간에 잠금을 공유해야합니다. 그들은 잠금 Object에 대한 고유 잠금 또는 java.util.concurrent.locks.ReentrantLock을 사용하는 명시 적 잠금을 공유 할 수 있습니다.

나는 고유 잠금에 대한 샘플 코드를 제공하고 있습니다 :

public class MyThread implements Runnable{ 

    Input ip; 
    Object lock; 

    public MyThread(Input ip, Object lock){ 
     this.ip = ip; 
     this.lock = lock; 
    } 

    @Override 
    public void run() { 
     int index = -1;  
     while((index=ip.getIndex())!=-1){ 
      synchronized(lock) { 
       System.out.println(Thread.currentThread().getName()); 
       ip.print(index); 
      } 
     } 
    } 
} 


public class Caller { 

    public static void main(String[] args) throws InterruptedException { 
     Input ip = new Input(); 
     Object lock = new Object(); 
     Thread t1 = new Thread(new MyThread(ip, lock), "Thread1"); 
     Thread t2 = new Thread(new MyThread(ip, lock), "Thread2"); 
     t1.start(); 
     t2.start(); 
     t1.join(); 
     t2.join(); 
    } 
} 

는 참고 : 이것은 단지 "의 ThreadX n은"함께 인쇄 할 수 있도록 할 것이다. 출력이 Input 배열의 정확한 순서를 따르는 것은 아닙니다.

BTW, 생성자에서 Thread을 시작하는 것은 위험하므로 피해야합니다. 원래 코드를 약간 변경했습니다.

+0

"... 생성자에서 스레드를 시작하는 것은 위험합니다"잠재적으로 개체가 완전히 초기화되기 전에 스레드가 개체에 액세스 할 수 있기 때문에 위험합니다. 그것은 "누설 _this_"또는 "안전하지 않은 출판물"이라고도합니다. Java 언어 스펙에 따르면 다른 스레드가 객체의 생성자가 반환되기 전에 다른 스레드가 객체에 대한 참조를 보유하면 다른 스레드에서 볼 수있는 객체의 상태가 _undefined_입니다. –

0

저수준 대기 알림 방법을 사용하여 아래 접근 방식을 사용할 수 있습니다.

package com.thread; 

/*Print 1 to 15 together by 2 threads*/ 

public class Print1To15 { 

    static int[] input = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 

    public static void main(String[] args) throws InterruptedException { 
     MyThread t1 = new MyThread(input); 
     MyThread t2 = new MyThread(input); 
     Thread thread1 = new Thread(t1, "Thread 1"); 
     Thread thread2 = new Thread(t2, "Thread 2"); 

     thread1.start(); 
     thread2.start(); 
     thread1.join(); 
     thread2.join(); 
    } 
} 

class MyThread implements Runnable { 
    int[] array; 
    static int i = 0; 
    final static Object obj = new Object(); 

    MyThread(int[] array) { 
     this.array = array; 
    } 

    @Override 
    public void run() { 
     synchronized (obj) { 
      while (i <= 14) { 
       if (array[i] % 2 != 0 && Thread.currentThread().getName().equals("Thread 1")) { 
        System.out.println(Thread.currentThread().getName() + " printing " + array[i]); 
        try { 
         obj.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } else if (array[i] % 2 == 0 && Thread.currentThread().getName().equals("Thread 2")) { 
        System.out.println(Thread.currentThread().getName() + " printing " + array[i]); 
        try { 
         obj.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       i++; 
       obj.notifyAll(); 
      } 
     } 
    } 
} 
관련 문제