2016-07-23 2 views
0

내가 제어 할 수있는 두 개의 스레드를 제공 할 필요가있는 곳에서 내가 시작, 중지, 일시 중지,이 스레드를 재개 할 수있는 곳과 별도로 제어 할 수있는 스레드를 제공해야한다. 이 스레드는 백그라운드에서 몇 가지 전용 기능을 수행합니다.자바에서 스레드 제어

현재 나는 그 안에 시작 및 정지 기능을 만들었지 만, 두 번째로 쳐다보고 나면 중지 기능을 호출 할 때 멈추지 않는 문제에 직면하고 있습니다.

이 작업을 테스트하기 위해 로그 작업을 쓰는 스레드를 구현했으며 정지 함수를 호출 할 때 두 번째 관찰했다. 실행 함수에서 구현 된 루프를 기다리는 while 루프에 갇혀있다. 완료하십시오.

: 내가 아래

멀티 스레딩에 조금 새로운 오전으로

누군가가이 문제의 원인을 파악하는 데 도움이 할 수있는 클래스가

컨트롤러 기본 및 보조 스레드가 제어해야하는 클래스를 구현

package com.threadcontrol; 

import com.threadcontrol.TimeStampGenerator; 

public abstract class Controller {  

    private static Thread threadPrim=null; 
    private static Thread threadSec=null; 
    private static Status statusPrim=Status.NOT_STARTED;  
    private static Status statusSec=Status.NOT_STARTED; 
    private static boolean completedPrim=false; 
    private static boolean completedSec=false; 
    private static RunnablePrim runnablePrim=new RunnablePrim(); 
    private static RunnableSec runnableSec=new RunnableSec(); 
    private static Logger loggerPrim=new Logger("LogPrim.txt"); 
    private static Logger loggerSec=new Logger("LogSec.txt"); 

    public enum Status {NOT_STARTED, RUNNING, PAUSED, STOPPED}; 
    public enum ThreadID {PRIM,SEC} 

    private static class RunnablePrim implements Runnable 
    {   
     @Override 
     public void run() 
     { 
      while(statusPrim==Status.RUNNING) 
      {    
       loggerPrim.log(TimeStampGenerator.get() + " Running Prim:");     
      }    
      completedPrim=true;   
     }   
    } 

    private static class RunnableSec implements Runnable 
    {   
     @Override 
     public void run() 
     {   
      while(statusSec==Status.RUNNING) 
      {    
       loggerSec.log(TimeStampGenerator.get() + " Running Sec:");    
      }    
      completedSec=true;   
     }   
    } 


    public static synchronized boolean start(ThreadID threadID) 
    { 
     switch(threadID) 
     { 
      case PRIM: 
       if(threadPrim==null) 
       { 
        threadPrim=new Thread(runnablePrim,"Primary Thread"); 
       } 
       statusPrim=Status.RUNNING; 
       threadPrim.start(); 
       return true; 
      case SEC: 
       if(threadSec==null) 
       { 
        threadSec=new Thread(runnableSec,"Secondary Thread"); 
       } 
       statusSec=Status.RUNNING; 
       threadSec.start(); 
       return true;    
     } 
     return false; 
    } 

    public static synchronized boolean stop(ThreadID threadID) 
    {  
     switch(threadID) 
     { 
      case PRIM:    
       statusPrim=Status.STOPPED;    
       while(completedPrim!=true) 
       { 

       } 
       completedPrim=false; 
       threadPrim=null;      
       return true; 
      case SEC: 
       statusSec=Status.STOPPED; 
       while(completedSec!=true) 
       { 

       } 
       completedSec=false; 
       threadSec=null;    
       return true; 
     } 
     return false; 
    } 

} 

테스트 클래스 :

package com.threadcontrol; 

public class TestController { 

    public static void main(String[] args) throws InterruptedException { 

     int timeout=10; 
     Logger logger=new Logger("LogMain.txt"); 

     logger.log(TimeStampGenerator.get() + " Starting Prim"); 
     Controller.start(Controller.ThreadID.PRIM);  
     Thread.sleep(timeout); 
     logger.log(TimeStampGenerator.get() + " Starting Sec"); 
     Controller.start(Controller.ThreadID.SEC); 
     Thread.sleep(timeout); 
     logger.log(TimeStampGenerator.get() + " Stopping Prim"); 
     Controller.stop(Controller.ThreadID.PRIM); 
     logger.log(TimeStampGenerator.get() + " Stopped Prim"); 
     Thread.sleep(timeout); 
     logger.log(TimeStampGenerator.get() + " Stopping Sec"); 
     Controller.stop(Controller.ThreadID.SEC); 
     logger.log(TimeStampGenerator.get() + " Stopped Sec"); 
     logger.log(TimeStampGenerator.get() + " Restarting"); 
     logger.log(TimeStampGenerator.get() + " Starting Prim"); 
     Controller.start(Controller.ThreadID.PRIM);  
     Thread.sleep(timeout); 
     logger.log(TimeStampGenerator.get() + " Starting Sec"); 
     Controller.start(Controller.ThreadID.SEC); 
     Thread.sleep(timeout); 
     logger.log(TimeStampGenerator.get() + " Stopping Prim"); 
     Controller.stop(Controller.ThreadID.PRIM); 
     logger.log(TimeStampGenerator.get() + " Stopped Prim"); 
     Thread.sleep(timeout); 
     logger.log(TimeStampGenerator.get() + " Stopping Sec"); 
     Controller.stop(Controller.ThreadID.SEC); 
     logger.log(TimeStampGenerator.get() + " Stopped Sec"); 
     logger.log(TimeStampGenerator.get() + " Exiting"); 

    } 

} 

개 Logger 클래스, 단지 스레드 동작을 테스트하기 위해 구현 :

package com.threadcontrol; 

import java.io.BufferedWriter; 
import java.io.File; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.io.PrintWriter; 

public class Logger { 

    private static String projPath=System.getProperty("user.dir"); 
    private String filePath; 

    public Logger(String fileName) 
    { 
     filePath=projPath + "\\data\\" + fileName; 
     File file=new File(filePath); 
     try 
     {   
      PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, false))); 
      out.flush(); 
      out.close(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void log(String data) 
    {   
     File file=new File(filePath); 
     try 
     {   
      PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true))); 
      out.println(data); 
      out.close(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

TimeStampGenerator 클래스를 그냥 스레드 동작을 테스트하기 위해 구현 :

2016_07_23_21_01_11_160 Starting Prim 
2016_07_23_21_01_11_320 Starting Sec 
2016_07_23_21_01_11_331 Stopping Prim 
2016_07_23_21_01_11_333 Stopped Prim 
2016_07_23_21_01_11_345 Stopping Sec 
2016_07_23_21_01_11_346 Stopped Sec 
2016_07_23_21_01_11_347 Restarting 
2016_07_23_21_01_11_348 Starting Prim 
2016_07_23_21_01_11_359 Starting Sec 
2016_07_23_21_01_11_371 Stopping Prim 
+0

글쎄, 우선, 거의 모든 Controller''에서 그 인스턴스 변수의 스레드 클래스로 이동해야하며, 하나의 스레드 클래스가 아닌 두 가지가 있어야한다. 그것은 코드를 많이 정리할 것입니다. – markspace

답변

1

때문에 : 메인 로그에서

package com.threadcontrol; 

import java.text.SimpleDateFormat; 
import java.util.Date; 

public abstract class TimeStampGenerator { 

    public static String get() 
    { 
     Date currentTimeStamp=new Date(); 
     SimpleDateFormat fmt=new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS"); 
     String tsStr=fmt.format(currentTimeStamp); 
     return tsStr; 
    } 
} 

출력 당신은 컨트롤 변수에 기반하여 두 개의 쓰레드를 제어하려고합니다. 이 4 명의 회원에게 volatile 키워드를 사용하십시오.

private static volatile Status statusPrim=Status.NOT_STARTED;  
private static volatile Status statusSec=Status.NOT_STARTED; 
private static volatile boolean completedPrim=false; 
private static volatile boolean completedSec=false; 

Do you ever use the volatile keyword in Java?

+0

그것은 작동했습니다. 감사. – user3422841

+0

@markspace에서 언급했듯이 코드가 좋지 않으므로 여러 스레드에 대한 자료를 읽어 보시기 바랍니다. – Happier

+0

예, 고마워요. 확실히 코드 개선을 위해 노력할 것입니다. – user3422841