【问题标题】: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();

现在的问题是,在启动线程后,它们并不总是立即开始运行,这意味着我会在建立连接之前发送我的请求。有没有一种简单的方法(不使用锁或互斥锁)可以确保我只在线程启动后才返回主程序? (我当然不想等待它们结束,因为它们永远不会结束。只需运行第一个命令一次 :) 此外,如果有更好的方法在后台运行进程而不是让这两个单独的线程,那也会很棒!)

谢谢!

【问题讨论】:

    标签: java multithreading ssh


    【解决方案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何时成功设置端口转发。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多