2017-11-22 1 views
1

http://www.siddhartha.ac.in/downloads/JP_Lab_Record2.pdf.여기서 for 루프의 모든 반복에 스레드를 재사용 할 수 있습니까?

쓰레드가 인 다중 스레드 응용 프로그램을 구현하는 Java 프로그램을 작성하십시오. 첫 번째 스레드는 매 초마다 임의의 정수를 생성하고 값이 짝수이면 두 번째 스레드는 의 제곱을 계산하고 인쇄합니다. 값이 홀수 인 경우 세 번째 스레드는 숫자 큐브의 값을 인쇄합니다. main 방법에

import java.util.*; 
class even implements Runnable 
{ 
    public int x; 
    public even(int x) 
    { 
     this.x = x; 
    } 
    public void run() 
    { 
     System.out.println("New Thread "+ x +" is EVEN and Square of " + x + " is: " + x * x); 
    } 
} 
class odd implements Runnable 
{ 
    public int x; 
    public odd(int x) 
    { 
     this.x = x; 
    } 
    public void run() 
    { 
     System.out.println("New Thread "+ x +" is ODD and Cube of " + x + " is: " + x * x * x); 
    } 
} 
class A extends Thread 
{ 
    public void run() 
    { 
     int num = 0; 
     Random r = new Random(); 
     try 
      { 
       for (int i = 0; i < 5; i++) 
        { 
         num = r.nextInt(100); 
         System.out.println("Main Thread and Generated Number is " + num); 
         if (num % 2 == 0) 
          { 
           Thread t1 = new Thread(new even(num)); 
       t1.start(); 
          } else { 
          Thread t2 = new Thread(new odd(num)); 
          t2.start(); 
      } 
         Thread.sleep(1000); 
      System.out.println("--------------------------------------"); 
        } 
      } 
     catch (Exception ex) 
      { 
       System.out.println(ex.getMessage()); 
      } 
    } 
} 
public class JavaProgram5 
{ 
    public static void main(String[] args) 
    { 
     A a = new A(); 
     a.start(); 
    } 
} 

이 루프의 각 반복에 대해, 두 개의 새로운 스레드가 생성된다. for 루프의 모든 반복에 대해 두 스레드를 재사용 할 수 있습니까?

감사합니다.

+0

왜 여러 스레드에서이 작업을 수행하고 있습니까? 많은 동시성 문제가 발생할 수 있습니다. 왜 단지 하나의 스레드가 값을 인쇄하지 않는가? – FredK

+1

@FredK 동기화 문제를 만들기 위해 고안된 과제 인 것 같습니다 –

+1

@ 존 과제 였지만 과제를 넘어서 생각하고 있습니다. – Ben

답변

1

스레드는 생각하는대로 재사용 할 수 없습니다. 실제로 숫자를 생성 할 때마다 신선한 스레드를 실제로 시작하고 있습니다. 이 시점에서 계산을위한 별도의 스레드가 전혀 없을 수도 있습니다.

질문의 하위 텍스트는 항상 3 개의 스레드가 실행 중임을 나타냅니다. 그것은 당신의 문제를 본질적으로 두 소비자의 생산자가되게합니다. 유일한 단서는 소비자가 지능적으로 행동하고 필요한 데이터 만 수집해야한다는 것입니다.

처리 코드는 올바른 트랙에서 꺼져 있습니다. 새로운 스레드를 시작하는 대신 notify (실제로는 notifyAll) 스레드는 EvenOdd을 실행해야합니다.

매초마다 하나의 항목을 생성하므로 실제로 적절한 대기열이 필요하지 않습니다. 단일 Integer 개체는 소비되지 않은 번호를 저장하기에 충분합니다. 상대적으로 구형 아키텍처에서도 1 초 이상 걸리면 다른 문제가 발생할 수 있습니다. int 대신 Integer을 사용하는 이유는 객체가 이미 소비되었음을 대기중인 스레드에 알릴 수 있어야한다는 것입니다.이 경우에는 null을 반환하는 것이 매우 쉬운 것처럼 보입니다. 생성 된 정수가 peekget 통해 액세스 될 수있는 필드에 배치된다

class Producer implements Runnable, IntConsumer 
{ 
    private Integer buffer = null; 

    public void run() 
    { 
     new Random().ints().forEach(this); 
    } 

    public void accept(int i) 
    { 
     synchronized(this) { 
      this.buffer = i; 
      this.notifyAll(); 
     } 
     try { 
      Thread.sleep(1000L); 
     } catch(InterruptedException ie) { 
      throw new RuntimeException("Producer interrupted!"); 
     } 
    } 

    public Integer peek() 
    { 
     return this.buffer; 
    } 

    public synchronized Integer get() 
    { 
     Integer i = peek(); 
     this.buffer = null; 
     return i; 
    } 
} 

통지. 버퍼를 지우는 get처럼 생성 코드가 생성자 객체에 잠급니다. 이렇게하면 한 번에 하나의 엔티티 만 값을 수정할 수 있습니다.

일반적으로 소비자와 제작자는 공유 스택이나 대기열 개체 또는 비슷한 것을 통해 통신합니다. 동기화는 큐에 의해 수행되며 LinkedBlockingQueue 또는 ArrayBlockingQueue입니다.이 간단한 경우 생성자는 큐 기능을 구현하므로 소비자는 제작자를 인식해야합니다.

소비자 스레드는 많은 공통 기능을 가지고 있습니다. 둘 다 생산자의 통지를 기다려야하고, 잠금 장치를 획득하고, 다음 오브젝트가 사용되지 않아서 속해 있는지 확인한 다음 소비하거나 기다리게해야합니다. 에러를 피하기 위해 check-then-get 연산은 모두 원자 적이어야한다. 이 모든 것은 기본 클래스에서 쉽게 인코딩 될 수 있습니다. 이 클래스는 확인 숫자를 처리하는 추상적 인 방법이있을 것이다 다음 숫자 입력의 패리티, 그리고 그들이에 적합하는 숫자를 처리하는 경우

public abstract class Consumer implements Runnable 
{ 
    private final Producer producer; 

    public Consumer(Producer producer) 
    { 
     this.producer = producer; 
    } 

    public void run() 
    { 
     while(true) { 
      synchronized(this.producer) { 
       Integer i = this.producer.peek(); 
       if(i != null && check(i)) { 
        this.producer.get(); 
        process(i); 
       } 
       try { 
        this.producer.wait(); 
       } catch(InterruptedException ie) { 
        throw new RuntimeException("Consumer interrupted!"); 
       } 
      } 
     } 
    } 

    public abstract boolean check(int i); 

    public abstract void process(int i); 
} 

구체적인 구현은 확인합니다. checkprocessInteger 대신 int을 수락함으로써 생산자가 비어 있는지 확인하는 것은 자신의 책임이 아니라는 점을 강조합니다. 마지막으로

public class Even extends Consumer 
{ 
    public Even(Producer producer) 
    { 
     super(producer); 
    } 

    public boolean check(int i) 
    { 
     return (i % 2) == 0; 
    } 

    public void process(int i) 
    { 
     System.out.println("x=" + i + "; x^2=" + (i * i)); 
    } 
} 

public class Odd extends Consumer 
{ 
    public Odd(Producer producer) 
    { 
     super(producer); 
    } 

    public boolean check(int i) 
    { 
     return (i % 2) != 0; 
    } 

    public void process(int i) 
    { 
     System.out.println("x=" + i + "; x^3=" + (i * i * i)); 
    } 
} 

함께 모든 것을 묶는 main 방법을 포함하는 드라이버 :

public class Driver 
{ 
    public static void main(String[] args) 
    { 
     Producer prod = new Producer(); 
     new Thread(new Even(prod)).start(); 
     new Thread(new Odd(prod)).start(); 
     new Thread(prod).start(); 
    } 
} 

당신은 메인 스레드를 대기, 초기 힘 main 종료에 문제가있는 경우 제작자가 다음과 같이 (영원히) 끝내기 위해 :

Thread t = new Thread(prod); 
t.start(); 
t.join(); 
는 는 (리눅스 이상에) Ctrl+C를 누를 때까지 다음과 같은 출력, 매초마다를 생성합니다 코드

:

x=966307133; x^3=-1676528219 
x=1271569805; x^3=-1481001707 
x=456385150; x^2=-1701399036 
x=-474801821; x^3=-813682373 
x=-1046547765; x^3=927976307 
x=-148577454; x^2=-185956796 
x=-14905035; x^3=-1126539123 
x=2071820769; x^3=-1426032223 
x=1075272421; x^3=1952259101 
x=-895041093; x^3=-978791741 
x=-2054472224; x^2=3441664 
... 
0

fixedThread의 pool.it를 사용하면 스레드를 재사용

  import java.util.Random; 
      import java.util.concurrent.ExecutorService; 
      import java.util.concurrent.Executors; 
      import java.util.concurrent.TimeUnit; 


      public class MainClass { 

       public static void main(String[] args){ 


         A a = new A(); 
         a.start(); 

       } 

      } 

      class A extends Thread 
      { 
       public void run() 
       { 

        ExecutorService executorService = Executors.newFixedThreadPool(2); 
        int num = 0; 
        Random r = new Random(); 
        try 
         { 
          for (int i = 0; i < 5; i++) 
           { 
            num = r.nextInt(100); 
            System.out.println("Main Thread and Generated Number is " + num); 
            if (num % 2 == 0) 
             { 
             executorService.submit(new even(num)); 

             } else { 
              executorService.submit(new odd(num)); 

         } 
            Thread.sleep(1000); 
         System.out.println("--------------------------------------"); 
           } 
         } 
        catch (Exception ex) 
         { 
          System.out.println(ex.getMessage()); 
         } 
       finally { 
        executorService.shutdown(); 
       } 
       try { 
        executorService.awaitTermination(1, TimeUnit.HOURS); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       } 
      } 

      class even implements Runnable 
      { 
       public int x; 
       public even(int x) 
       { 
        this.x = x; 
       } 
       public void run() 
       { 
        System.out.println("New Thread "+ x +" is EVEN and Square of " + x + " is: " + x * x); 
       } 
      } 
      class odd implements Runnable 
      { 
       public int x; 
       public odd(int x) 
       { 
        this.x = x; 
       } 
       public void run() 
       { 
        System.out.println("New Thread "+ x +" is ODD and 
       Cube of " + x + " is: " + x * x * x); 
       } 
      }