从Java执行julia脚本

时间:2015-12-03 16:07:09

标签: java julia execute

我用ZeroMQ编写Julia脚本。

我的目标是在两个脚本之间与ZMQ进行通信。这是一个例子:

# script1
using ZMQ
ctx = ZMQ.Context()
sockDealer = ZMQ.Socket(ctx, DEALER)
ZMQ.set_identity(sockDealer, "idA")
ZMQ.connect(sockDealer, "tcp://localhost:5555")
ZMQ.send(sockDealer, "hello world!")
ZMQ.close(sockDealer)
ZMQ.close(ctx)



#script2
using ZMQ

function pollrecv(socket::ZMQ.Socket,zmsg::Message)
  rc = -1
  while true
    rc = ccall((:zmq_msg_recv, ZMQ.zmq), Cint, (Ptr{Message}, Ptr{Void}, Cint),
                    &zmsg, socket.data, ZMQ.ZMQ_DONTWAIT)
  if rc == -1
    # Base.Libc.EAGAIN = 11
    # Problem unsolved: Failure to find Base.Libc.EAGAIN
    if !(ZMQ.zmq_errno() == 11)
      throw(ZMQ.StateError(ZMQ.jl_zmq_error_str()))
    end
    return false
    else
      ZMQ.get_events(socket) != 0 && notify(socket)
      break
    end
  end
  return true
end

ctx = ZMQ.Context()
sockRouter = ZMQ.Socket(ctx, ROUTER)
ZMQ.bind(sockRouter, "tcp://*:5555")
fini = false
while !fini
  println("listening...")
  idSock = Message()
  while pollrecv(sockRouter, idSock)
    msg = ZMQ.recv(sockRouter)
    println("msg recv: " * bytestring(msg))
    fini = true
  end
  sleep(1)
end
ZMQ.close(sockRouter)
ZMQ.close(ctx)

我可以在命令提示符下使用Julia执行它们。一切都很顺利。脚本2可以接收脚本1的消息。

现在,我需要从Java执行它们。这意味着我需要创建一个像控制器一样的java项目。这是我的Java项目:

public class Container {

    private Vector<String[]> commands;

    public Container() {
        this.commands = new Vector<String[]>();
    }

    public void addCommand(String[] strs) {
        this.commands.addElement(strs);
    }

    public void execute() {
        for(int i = 0; i < this.commands.size(); i++) {
            try {
                Process p = Runtime.getRuntime().exec(this.commands.get(i));
                if(p.waitFor() != 0){
                    System.err.println("exit value = " + p.exitValue());
                }
                BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
                StringBuffer stringBuffer = new StringBuffer();
                String line = null;
                while((line = in.readLine()) != null){
                    stringBuffer.append(line + "-");
                }
                System.out.println(stringBuffer.toString());

            } catch (IOException ex) {
                // TODO Auto-generated catch block
                ex.printStackTrace();
            } catch(InterruptedException e){
                System.err.println(e);
            }
        }
    }
}


//main
public class Main {
    public static void main(String[] args) {
        Container c = new Container();

        String[] script1 = {"/usr/bin/julia", "/home/thomas/Julia/script1.jl"};
        String[] script2 = {"/usr/bin/julia", "/home/thomas/Julia/script2.jl"};
        c.addCommand(script1);
        c.addCommand(script2);
        c.execute();
    }
}

然而,当我运行我的java项目时,我可以看到它一直在运行,但我在控制台上看不到任何内容:没有结果,没有消息,没有错误。

我认为我的java项目有问题。

2 个答案:

答案 0 :(得分:1)

您需要同时运行这两个脚本:script2是服务器脚本,因此它应该在您运行script1时运行。就像现在一样,Process.waitFor()将在下一次script1迭代中执行服务器脚本script2之前等待客户端脚本for完成。

你可以这样开始:

    String[] clientScript = { "/usr/bin/julia", "/home/thomas/Julia/script1.jl" };
    String[] serverScript = { "/usr/bin/julia", "/home/thomas/Julia/script2.jl" };

    Process server = Runtime.getRuntime().exec(serverScript);
    Process client = Runtime.getRuntime().exec(clientScript);

并实例化两个线程来读取它们的输出:

    (new ProcessReader(server)).start();
    (new ProcessReader(client)).start();
使用

public class ProcessReader extends Thread {
    private Process p;

    public ProcessReader(Process p) {
        this.p = p;
    }

    @Override
    public void run() {
        BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
        try {
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println("Read: " + line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

虽然,clientScript不会产生任何输出,但你可以这样做 启动脚本,只读取服务器脚本的输出 - 不需要线程。

还有一件事需要考虑:在serverScript尝试连接之前,listening...必须是clientScript。所以你可能想这样做:

    Process server = Runtime.getRuntime().exec(serverScript);
    BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
    if ( in.readLine().equals("listening...") ) {
        Process client = Runtime.getRuntime().exec(clientScript);

        String line;
        while ( (line=in.readLine()) != null )
            System.out.println("Read: " + line );
    }

答案 1 :(得分:0)

由于这不是您问题的特定答案,因此这可能对您或尝试执行类似工作的其他用户有所帮助。

JuliaCaller是用于从Java调用Julia的早期库。它以Java进程的形式执行Julia可执行文件,并在Julia端运行脚本。该脚本将打开一个侦听给定端口号的TCP服务器。然后执行从Java发送的每个命令,语句或表达式,并将结果以JSON格式发送回Java。

该库还实现了标准的javax.script接口,这意味着Julia库,函数和程序可以像用Java(模拟)实现的脚本语言一样运行。

这里是示例:

function [bw_seg] = watershedImage(img, bw, param)

%% Parameters extraction
stats = regionprops(bw, img, 'Area', 'Image', 'PixelIdxList', 'BoundingBox');
param.medianarea = median([stats.Area]);

% Select only the BLOBs with sufficient area for watershed segmentation
thresh = 0.6*param.medianarea;                  % lower area threshold
BLOBind = find([stats.Area] > thresh);          % BLOB indices
boundingboxbuffer = 5;                          % in pixels
watershed_temp = false(size(img));
bw_seg = logical(bw);

%% Watershed on each individual binary section of the mask
parfor i = 1:length(BLOBind)

    % Extract each BLOB by cropping (with a buffer 'safety' border) the
    % bounding box of each BLOB
    r = round(stats(BLOBind(i)).BoundingBox);
    boundingboxBLOB = [max(r(1)-boundingboxbuffer,1) max(r(2)-boundingboxbuffer,1) ...
        r(3)+2*boundingboxbuffer-1 r(4)+2*boundingboxbuffer-1];
    img_BLOB = imcrop(img, boundingboxBLOB);

    % Crop the same region accordingly from the binary mask
    bw_BLOB = false(size(bw));
    bw_BLOB(stats(BLOBind(i)).PixelIdxList) = 1;
    bw_BLOB = imcrop(bw_BLOB, boundingboxBLOB);

    % Watershed segmentation (a written watershed segmentation algorithm)
    L = watershedBLOB(img_BLOB, bw_BLOB, param);

    %%%%%% I'm getting errors here for 'watershed_temp' and 'img_seg'!!! %%%%%%%
    if max(max(bwlabel(L))) > 0 && sum(sum(L)) >= 0.6*sum(sum(bw_BLOB))
        [f1, f2] = find(L > 0);
        fr = f1 + boundingboxBLOB(2) - 1;
        fc = f2 + boundingboxBLOB(1) - 1;
        watershed_temp(sub2ind(size(img), fr, fc)) = L(sub2ind(size(L), f1, f2));
        bw_seg(stats(BLOBind(i)).PixelIdxList) = 0;
    end

end

bw_seg = imfill(logical(bw_seg) | watershed_temp, 'holes');

end

在GitHub页面上提供了更多示例。

Source code with Apache License