1

样本执行服务

 static class MyRunnable implements Runnable {

    private String serverName;

    public MyRunnable(String serverName) {
        super();
        this.serverName = serverName;
    }

    @Override
    public void run() {
        ...
        conn = new ch.ethz.ssh2.Connection(serverName);
        conn.connect();

        boolean isAuthenticated = conn.authenticateWithPassword(user, pass);
        logger.info("Connecting to " + server);

        if (isAuthenticated == false) {
            logger.info(server + " Please check credentials");
        }

        sess = conn.openSession();
        ...

    }

}

public static void main(String[] args) {
    List<String> serverList = ...;
    ExecutorService executor = Executors.newFixedThreadPool(20);

    for (String serverName : serverList) {
        MyRunnable r = new MyRunnable(serverName);
        executor.execute(r);
    }

    executor.shutdown();
    executor.awaitTermination(1, TimeUnit.HOURS);
}

这是我的执行程序服务的示例代码。但是,当我遇到无法连接或连接时间过长的服务器时,使用这种逻辑会在我的应用程序中创建一个挂起时间。如果连接时间超过 x 时间,我想结束/终止线程。如果线程任务在 2 秒内没有连接到服务器,我该如何终止它。

试图

       ThreadPoolExecutor executor = new ThreadPoolExecutor(
                10, 25, 500, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1));

我添加了以下代码,但如果它花费的时间超过 2000 毫秒,显然它不会结束线程。

尝试 2

Future<?> future = executor.submit( new task));
            try {
                future.get(2000, TimeUnit.MILLISECONDS); // This waits timeout seconds; returns null
            }

            catch(TimeoutException e) {
                future.cancel(true);
               // System.out.println(server + "name");
            } 
4

4 回答 4

1

你必须先做awaitTermination(),然后检查返回值,然后再做shutdownNow(). shutdown()不保证立即停止服务,它只是停止接受新作业,并等待所有作业按顺序完成。shutdownNow()另一方面,停止接受新任务,主动尝试停止所有正在运行的任务,并且不启动任何新任务,返回所有等待执行任务的列表。

来自JavaDocs

以下方法分两个阶段关闭 ExecutorService,首先调用 shutdown 拒绝传入任务,然后在必要时调用 shutdownNow 取消任何延迟任务:

 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }
于 2017-06-15T18:12:44.823 回答
1

如果线程任务在 2 秒内没有连接到服务器,我该如何终止它。

这通常很难做到,因为即使您中断线程(就像提到的其他答案一样),也不能保证线程会停止。中断只是在线程上设置一个标志,由代码检测状态并停止。这意味着大量线程可能在后台等待连接。

但是,在您的情况下,您正在使用该ch.ethz.ssh2.Connection.connect()方法。原来有一个连接方法需要超时。我认为您想要以下内容:

// try to connect for 2 seconds
conn.connect(null, 2000, 0);

引用连接方法 javadocs

如果发生超时(connectTimeout 或 kexTimeout),则会引发 SocketTimeoutException。

于 2017-06-16T22:24:00.927 回答
0

你可以随时调用future.get(timeout...) 如果它还没有完成它会返回超时异常......然后你可以调用future.cancel()。

于 2017-06-15T18:25:22.813 回答
0

只要您在 Java 中处理线程,停止线程的唯一安全方法就是中断它。你可以shutdown()先打电话,然后等待。此方法不会中断线程。

如果它没有帮助,那么您调用shutdownNow()which 通过将每个线程的中断标志设置为 true 来尝试取消任务。在这种情况下,如果线程被阻塞/等待,则会抛出 InterruptedException。如果您在任务中的某处检查中断标志,那么您也很好。

但是,如果您别无选择,只能停止线程,您仍然可以这样做。访问工人的一种可能的解决方案是在自定义线程工厂的帮助下跟踪 ThreadPoolExecutor 中所有创建的线程。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class TestThreadPoolEx {

    static class CustomThreadFactory implements ThreadFactory {
        private List<Thread> threads = new ArrayList<>();

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            threads.add(t);
            return t;
        }

        public List<Thread> getThreads() {
            return threads;
        }

        public void stopThreads() {
            for(Thread t : threads) {
                if(t.isAlive()) {
                    try {
                        t.stop();
                    } catch (Exception e) {
                        //NOP
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CustomThreadFactory factory = new CustomThreadFactory();
        ExecutorService ex = Executors.newFixedThreadPool(1, factory);
        ex.submit(() -> {
            while(true);
        });
        ex.shutdown();
        ex.awaitTermination(5, TimeUnit.SECONDS);
        ex.shutdownNow();
        ex.awaitTermination(5, TimeUnit.SECONDS);
        factory.stopThreads();
    }
}

这肯定是不安全的,但应该符合您的要求。在这种情况下,它能够停止 while(true) 循环。取消任务将无法做到这一点。

于 2017-06-15T18:25:42.463 回答