Java 控制多线程的执行流
我有4个线程在运行,即A、B、C、D。 根据某些输入条件,执行顺序会有所不同。 对于输入“0”的ex,顺序为A->C->B-DJava 控制多线程的执行流,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
对于输入“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.
解决此问题的可能方法如下:
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(); }