java - 在java中控制线程

标签 java multithreading runnable

我正在尝试创建一些东西,除了主线程之外,我还必须提供两个可控线程,我可以在主线程中启动、停止、暂停、恢复这些线程,这些线程是我在抽象类中提供的。这些线程将在后台执行一些专用功能。

目前我已经在其中创建了启动和停止函数,但我面临一个问题,即在第二次启动后调用停止函数时,它没有停止。

我已经实现了将线程操作写入日志文件来测试这一点,并观察到当我第二次调用 stop 函数时,它陷入了 while 循环,该循环等待 run 函数中实现的循环完成。

有人可以帮助我找出导致此问题的原因,因为我对多线程不太陌生

下面是实现的类

应控制主线程和辅助线程的 Controller 类:

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 类,只是为了测试线程行为而实现的:

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;
    }
}

主日志输出:

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

最佳答案

因为您试图根据控制变量来控制两个线程。对这 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?

关于java - 在java中控制线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38543561/

相关文章:

java - Scala:如何概括不相关的 Java 类的行为

java - CDI @Interceptor 的@Priority 的含义是什么?

c# - 如何使Windows服务请求等到上一个请求完成

java - ExecutorCompletionService 和 FixThreadPool 执行器之间的区别

java - 修改服务器以允许多个客户端同时连接

Java:当被另一个线程中断时,如何在线程上捕获 InterruptedException?

java - 将值从 jsp 发送到 jsp

java - 获取 jar 的所有导入类

c++ - 条件变量卡在等待中

java - 添加属性文件以构建可运行 jar 的路径