如何确保只有在子线程启动后主线程才能继续?
Posted
技术标签:
【中文标题】如何确保只有在子线程启动后主线程才能继续?【英文标题】:How to make sure the main thread continues only after child thread has started? 【发布时间】:2014-02-06 00:38:02 【问题描述】:我正在尝试编写一个程序,首先 ssh'es 到两台不同的机器,然后对它们执行一些 http 请求。这意味着为了能够执行我的 http 请求,ssh 隧道应该运行。
我所做的是我有两个线程,每个线程都运行 ssh 命令到其中一个框:
Thread thread1 = new Thread(new Runnable()
public void run()
try
Process p1 = Runtime.getRuntime().exec("ssh -A -L12345:localhost:54321 firsthost.com");
p1.waitFor();
catch (Exception e)
) ;
thread1.start();
Thread thread2 = new Thread(new Runnable()
public void run()
try
Process p2 = Runtime.getRuntime().exec("ssh -A -L12345:localhost:54321 secondhost.com");
p2.waitFor();
catch (Exception e)
) ;
thread2.start();
现在的问题是,在启动线程后,它们并不总是立即开始运行,这意味着我会在建立连接之前发送我的请求。有没有一种简单的方法(不使用锁或互斥锁)可以确保我只在线程启动后才返回主程序? (我当然不想等待它们结束,因为它们永远不会结束。只需运行第一个命令一次 :) 此外,如果有更好的方法在后台运行进程而不是让这两个单独的线程,那也会很棒!)
谢谢!
【问题讨论】:
【参考方案1】:尝试添加-f
和-N
标志,以便在设置端口转发后告诉ssh 自己后台运行。然后您可以在主线程中执行ssh
命令并等待它们退出(即后台本身),然后再继续。
-f
在命令执行之前请求 ssh 进入后台。如果 ssh 将要求输入密码或密码,但用户希望它在后台使用,这很有用。这意味着
-n
。在远程站点启动 X11 程序的推荐方法是使用ssh -f host xterm
之类的东西。如果 ExitOnForwardFailure 配置选项设置为“yes”,则以
-f
启动的客户端将等待所有远程端口转发成功建立,然后再将其置于后台。
-N
不要执行远程命令。这对于仅转发端口很有用(仅限协议版本 2)。
(很遗憾,我目前无法对此进行测试。如果不起作用,请致歉。)
【讨论】:
非常感谢!是的 -f 和 -N 它有效。我现在只需要弄清楚如何避免输入我的密码。 (当我从 shell 执行 ssh 时,它不会以某种方式提示我输入密码,但它会以这种方式提示。)但除此之外,这是一个非常简单的解决方案 :)【参考方案2】:首先,JDK5 以后不鼓励直接使用线程。包装完好的 Executor 将为我们完成这项工作。如果您有较低版本的 java 或者您仍想以这种方式执行此操作,那么这里有一个快速解决方案,
公共类主
public static void main(String... objs) throws Exception
final Process1Thread p1Thread = new Process1Thread();
final Process2Thread p2Thread = new Process2Thread();
Thread p1 = new Thread(p1Thread);
Thread p2 = new Thread(p2Thread);
p1.start(); p2.start();
while(true)
if(p1Thread.isFinishedCommand() && p2Thread.isFinishedCommand())
//send commands
System.out.println("sending commands");
break;
interface FinishedCommand
boolean isFinishedCommand();
static class Process1Thread implements Runnable, FinishedCommand
private boolean finished = false;
@Override
public boolean isFinishedCommand()
synchronized(this)
return finished;
@Override
public void run()
try
final Process p2 = Runtime.getRuntime().exec("dir");
synchronized(this)
finished = true;
p2.waitFor();
catch (Exception e)
e.printStackTrace();
static class Process2Thread implements Runnable, FinishedCommand
private boolean finished = false;
@Override
public boolean isFinishedCommand()
synchronized(this)
return finished;
@Override
public void run()
try
final Process p2 = Runtime.getRuntime().exec("dir");
synchronized(this)
finished = true;
p2.waitFor();
catch (Exception e)
e.printStackTrace();
问候 礼州
【讨论】:
【参考方案3】:您可以使用 thread1.getState() 方法来获取线程的状态。在你可以 thread1.start() 之后,它应该被移动到 RUNNABLE 状态。当 thread1 等待进程完成时,它将处于 BLOCKED 状态。
【讨论】:
这无助于知道ssh
何时成功设置端口转发。以上是关于如何确保只有在子线程启动后主线程才能继续?的主要内容,如果未能解决你的问题,请参考以下文章