告诉ThreadPoolExecutor什么时候应该继续

时间:2012-08-16 18:44:12

标签: java multithreading port threadpool threadpoolexecutor

我必须通过某个端口将一组文件发送到多台计算机。事实是,每次调用发送文件的方法时,都会计算目标数据(地址和端口)。因此,使用为每个方法调用创建线程的循环,并使用try-catch语句围绕方法调用,以便BindException处理尝试使用已在使用的端口的程序的情况(不同的目标地址可能通过相同的端口接收消息)告诉线程等待几秒钟,然后重新启动以重试,并继续尝试直到不抛出异常(发送成功)。 我不知道为什么(虽然我第一次看到它时可以猜到),但Netbeans警告我,在循环中睡眠Thread对象不是最好的选择。然后我用Google搜索了一些信息,发现this link to another stackoverflow post, which looked so interesting(我从未听说过the ThreadPoolExecutor class)。我一直在阅读该链接和API以尝试改进我的程序,但我还不确定我应该如何在我的程序中应用它。有人可以帮忙吗?

编辑:重要的代码:

        for (Iterator<String> it = ConnectionsPanel.list.getSelectedValuesList().iterator(); it.hasNext();) {
        final String x = it.next();
        new Thread() {

            @Override
            public void run() {
                ConnectionsPanel.singleAddVideos(x);
            }
        }.start();
    }

    private static void singleAddVideos(String connName) {
    String newVideosInfo = "";

    for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
        newVideosInfo = newVideosInfo.concat(it.next().toString());
    }

    try {
        MassiveDesktopClient.sendMessage("hi", connName);
        if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
            MassiveDesktopClient.sendMessage(newVideosInfo, connName);
        }
    } catch (BindException ex) {
        MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
        try {
            Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
        } catch (InterruptedException ex1) {
            JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
        }
        ConnectionsPanel.singleAddVideos(connName);
        return;
    }

    for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
        try {
            MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
        } catch (BindException ex) {
            MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
            try {
                Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
            } catch (InterruptedException ex1) {
                JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
            }
            ConnectionsPanel.singleAddVideos(connName);
            return;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你的问题不是很清楚 - 我知道你要重新运行你的任务,直到它成功(没有BindException)。要做到这一点,你可以:

  • 尝试运行代码而不捕获异常
  • 捕获未来的例外
  • 如果失败,
  • 稍后重新安排任务

简化代码如下所示 - 添加错误消息并根据需要进行优化:

public static void main(String[] args) throws Exception {
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(corePoolSize);
    final String x = "video";
    Callable<Void> yourTask = new Callable<Void>() {
        @Override
        public Void call() throws BindException {
            ConnectionsPanel.singleAddVideos(x);
            return null;
        }
    };
    Future f = scheduler.submit(yourTask);
    boolean added = false; //it will retry until success
                           //you might use an int instead to retry
                           //n times only and avoid the risk of infinite loop
    while (!added) {
        try {
            f.get();
            added = true; //added set to true if no exception caught
        } catch (ExecutionException e) {
            if (e.getCause() instanceof BindException) {
                scheduler.schedule(yourTask, 3, TimeUnit.SECONDS); //reschedule in 3 seconds
            } else {
                //another exception was thrown => handle it
            }
        }
    }
}

public static class ConnectionsPanel {

    private static void singleAddVideos(String connName) throws BindException {
        String newVideosInfo = "";

        for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
            newVideosInfo = newVideosInfo.concat(it.next().toString());
        }

        MassiveDesktopClient.sendMessage("hi", connName);
        if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
            MassiveDesktopClient.sendMessage(newVideosInfo, connName);
        }

        for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
            MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
        }
    }
}