Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 控制多线程的执行流_Java_Multithreading - Fatal编程技术网

Java 控制多线程的执行流

Java 控制多线程的执行流,java,multithreading,Java,Multithreading,我有4个线程在运行,即A、B、C、D。 根据某些输入条件,执行顺序会有所不同。 对于输入“0”的ex,顺序为A->C->B-D 对于输入“1”,顺序为A->D->B-C您可以等待第一个线程完成,然后启动下一个线程: Thread A = ...; Thread B = ...; A.start(); // start thread A A.join(); // wait here until thread A finishes B.start(); B.join(); // and so on

我有4个线程在运行,即A、B、C、D。 根据某些输入条件,执行顺序会有所不同。 对于输入“0”的ex,顺序为A->C->B-D
对于输入“1”,顺序为A->D->B-C

您可以等待第一个线程完成,然后启动下一个线程:

Thread A = ...;
Thread B = ...;

A.start(); // start thread A
A.join(); // wait here until thread A finishes
B.start();
B.join();
// and so on.

解决此问题的可能方法如下:

  • 创建Thread类的ArrayList
  • 按照要执行的顺序将线程实例添加到此ArrayList
  • 迭代ArrayList,并在每个线程上逐个调用start方法和join方法
  • 线程的运行顺序将由插入ArrayList的顺序控制

    完整的工作示例如下:

    public class ThreadSequencer {
    
        private static List<Thread> threadSequence = new ArrayList<>();
        /*Create the threads. If not using Java 8, replace ThreadSequencer::printThreadName
         * with new Runnable() { public void run() { System.out.println(Thread.currentThread().getName());} }
         */
        private static Thread threadA = new Thread(ThreadSequencer::printThreadName);
        private static Thread threadB = new Thread(ThreadSequencer::printThreadName);
        private static Thread threadC = new Thread(ThreadSequencer::printThreadName);
        private static Thread threadD = new Thread(ThreadSequencer::printThreadName);
    
    
        private static void sequenceThreads(String input) {
            threadSequence.clear();
            if("0".equals(input)) {
                threadSequence.add(threadA);
                threadSequence.add(threadB);
                threadSequence.add(threadC);
                threadSequence.add(threadD);
            } else if("1".equals(input)) {
                threadSequence.add(threadB);
                threadSequence.add(threadA);
                threadSequence.add(threadC);
                threadSequence.add(threadD);
            }
        }
    
        public static void runThreads(String input) {
            sequenceThreads(input);
            for(Thread thread : threadSequence) {
                thread.start();
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    //handle exceptional cases
                    e.printStackTrace();
                }
            }
        }
    
        private static void printThreadName() {
            System.out.println(Thread.currentThread().getName());
        }
    
        public static void main(String []args) {
            runThreads("1");
        }
    }
    
    公共类线程序列器{
    私有静态列表threadSequence=new ArrayList();
    /*创建线程。如果不使用Java 8,请替换ThreadSequencer::printThreadName
    *使用新的Runnable(){public void run(){System.out.println(Thread.currentThread().getName());}
    */
    私有静态线程threadA=新线程(ThreadSequencer::printThreadName);
    私有静态线程threadB=新线程(ThreadSequencer::printThreadName);
    私有静态线程threadC=新线程(ThreadSequencer::printThreadName);
    私有静态线程threadD=新线程(ThreadSequencer::printThreadName);
    私有静态void sequenceThreads(字符串输入){
    threadSequence.clear();
    如果(“0”。等于(输入)){
    threadSequence.add(threadA);
    threadSequence.add(threadB);
    threadSequence.add(threadC);
    threadSequence.add(threadD);
    }否则,如果(“1”。等于(输入)){
    threadSequence.add(threadB);
    threadSequence.add(threadA);
    threadSequence.add(threadC);
    threadSequence.add(threadD);
    }
    }
    公共静态void运行线程(字符串输入){
    顺序线程(输入);
    用于(螺纹:螺纹顺序){
    thread.start();
    试一试{
    thread.join();
    }捕捉(中断异常e){
    //处理特殊情况
    e、 printStackTrace();
    }
    }
    }
    私有静态void printThreadName(){
    System.out.println(Thread.currentThread().getName());
    }
    公共静态void main(字符串[]args){
    运行线程(“1”);
    }
    }
    

    使用字符串调用runThreads方法,线程将按该顺序运行。也就是说,如果您不想按顺序运行线程,那么为什么要首先创建线程呢

    一般来说,您不应该希望控制线程的细节如此精细。然而,有时是有必要的。例如,在编写测试用例时。所以我写了一个线程调度程序,就是为了这个目的:


    滚动到文件的底部,您可以看到一个示例,说明了此类的用法。在为Java EE编写测试代码时帮了我很大的忙。

    这个答案是基于对OPs符号的假设阅读, “X->Y-Z”表示“线程X在Y和Z开始之前运行到完成”

    修补工程师福阿德的答案以符合OP的情况:

    Thread A = ...;
    Thread B = ...;
    Thread C ...
    Thread D ...
    
    if (input==0)
      {  A.start(); // start thread A
         A.join(); // wait here until thread A finishes
         C.start();
         C.join();
         B.start();
         D.start();
         B.join();
         D.join();
       }
    else
      {  A.start(); 
         A.join(); 
         D.start();
         D.join();
         B.start();
         C.start();
         B.join();
         C.join();
       }
    
    作为一个轻微的优化,a.start();A.join()语句对可以提升到条件语句之上

    OP似乎想做的是定义线程上的动态偏序。他的例子如上所述是可以解决的。通常,静态偏序(上面“if”的每个分支)不能由父线程使用“start”和“joins”来完成;各个线程必须进行连接,以确保以正确的顺序调用它们。要执行动态偏序,每个线程必须根据条件检查前置线程

    假设输入==0导致A->B,A->C,D->C,否则A->D,B->D,B->C: 您需要这样一个更混乱的解决方案(请原谅我的Java,我不是专家):

    我假设Java线程可以看到父线程中的变量(如果范围正确)。我还假设您可以不止一次地连接到一个线程,例如,从不同的位置多次调用a.join()就可以了


    如果您有10-12个具有复杂偏序的线程,那么编写此代码并使其正确运行是相当困难的。有一些语言可以直接表达偏序,以避免编写所有start/join-goo

    OP允许动态更改执行顺序。这并没有回答问题。@bot它确实回答了问题,但只回答了第一个序列。根据这个答案,他将能够完成其余的序列。我不同意。OP希望在运行时而不是编译时决定顺序。当你给他指出正确的方向时,你根本没有回答这个问题。你有没有考虑过这个问题,或者在我们为你解决这个问题时,你是要去吃午饭;)关于线程的全部要点是,您无法控制线程的运行顺序。从程序的角度来看,它们可以被认为是同时发生的。如果一个工作块要一个接一个地运行,那么把它们放在线程中是没有意义的。@Sachin请看我完整的例子的答案。@Sachin:我将“a->B”理解为“a在B之前运行并完成”,将“X->Y-Z”理解为“X在Y和Z之前运行并完成,Y和Z并行运行”@DavidWallace:您确实希望控制它们的运行顺序,以确保一个线程对另一个线程结果的依赖关系得到尊重。这是线程A在线程B之前的点。如果没有依赖关系,它们可以运行“纯并行”。当然,如果只有串行执行而没有并行性,这是毫无意义的,您不应该使用线程。但在更复杂的情况下,“纯并行”和“纯串行”之间存在中间地带;您可能需要线程执行的部分顺序。这使这成为一个有趣的问题
    Thread A = new Thread(workerA)...;
    Thread B = new Thread(workerB)...;
    Thread C = new Thread(workerC)...;
    Thread D = new Thread(workerD)...;
    
    workerA() {
       ... 
    }
    
    workerB() {
       if (input==0)
           A.join();
       ...
    }
    
    workerC() {
      if (input==0)
         { A.join(); D.join(); }
      else B.join();
    ...
    }
    
    workerD() {
      if (input==1)
         { A.join(); B.join(); }
      ...
    }
    
    A.start(); // start thread A
    B.start();
    C.start();
    D.start();
    if (input==0)
       { B.join(); C.join(); }
    else { C.join(); D.join(); }