我用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项目有问题。
答案 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页面上提供了更多示例。