首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有持久资源的Java线程

具有持久资源的Java线程
EN

Stack Overflow用户
提问于 2015-02-14 02:44:28
回答 1查看 172关注 0票数 1

我有一个工作线程池(一个ExecutorService)。

此池用于运行shell命令。

我使用shell (/bin/sh),而不是直接为可执行文件创建进程,因为我使用shell重定向(>)将输出直接写入磁盘,而不必通过JVM,以及其他一些细节。

生成shell进程需要2-3毫秒。

我希望每个线程保持一个shell进程,以避免启动它的开销。

如何允许每个线程拥有一个进程?

我正在考虑在线程局部变量中使用ThreadFactory

代码语言:javascript
复制
class ThreadFactory {
    Thread newThread(Runnable r) {
        return new Thread(new Runnable() {
            Process process = Runtime.getRuntime().exec("/bin/sh")
            try {
                // store process as thread local here
                r.run(); // then r can access thread local
            } catch(Exception e) {
                try {
                    process.close();
                } catch(Exception e) {
                }
                throw e;
            }
        });
    }
}

(或者,我可以在我的Thread中将Thread.currentThread()子类转换为该类。)

这是解决这个问题的好办法吗?

EN

回答 1

Stack Overflow用户

发布于 2015-02-14 08:41:23

我会将Process引用保存在一个连续执行命令的ProcessRunnable中。我认为比使用ThreadLocalThreadFactory更清晰。就像这样:

代码语言:javascript
复制
public class ShellCommandExecutor {

private int concurrency = 10;
private int capacity = 100;

private ExecutorService service = Executors.newFixedThreadPool(concurrency);
private BlockingQueue<String> commandsQueue = new LinkedBlockingQueue<>(capacity);

public void start() {
    for (int i = 0; i < concurrency; i++)
        service.submit(new Runnable() {
            @Override
            public void run() {
                //todo deal with ioexception
                Process process = Runtime.getRuntime().exec("/bin/sh");
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        String command = commandsQueue.take();
                        //todo execute commands using the same process per thread
                    }
                    catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        });
}

public void executeCommand(String command) throws InterruptedException {
    commandsQueue.put(command);
}

public void shutdown() {
    service.shutdownNow();
}
}

编辑:一种具有线程本地的解决方案,可以轻松地处理缓存的线程池:

代码语言:javascript
复制
public class ShellCommandExecutor2 {

    //todo limit queue
    private ExecutorService service = Executors.newCachedThreadPool();

    public void executeCommand(final String command) throws InterruptedException {

        service.submit(new Runnable() {
            @Override
            public void run() {
                Process process = ThreadLocalProcessFactory.get();
                //todo execute command
            }
        });
    }

    public void shutdown() {
        service.shutdownNow();
    }

    private static class ThreadLocalProcessFactory {

        private static final ThreadLocal<Process> processThreadLocal =
                new ThreadLocal<Process>() {
                    @Override protected Process initialValue() {
                        try {
                            return Runtime.getRuntime().exec("/bin/sh");
                        }
                        catch (IOException e) {
                            e.printStackTrace();
                            return null;
                        }
                    }
                };

        static Process get() {
            return processThreadLocal.get();
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28511864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档