1

我已经尝试了几乎所有方法来完成这项工作,但似乎我没有找到正确的方向。

这是实际情况:我在 Netbeans7.3 下使用 JSF2.2 和 GlashFish7。我的 JSF 应用程序应该创建第二个线程来运行(异步)无限循环。在这个无限循环中,我使用 WatchService (NIO) 检查特定文件夹的更改。WatchService 函数在单线程驱动的 jsf 页面中运行良好。但是我会在循环期间做其他事情,所以我需要这个异步方法,但我无法在单独的线程中运行它。

这是我的java类:

@Stateless
public class NewFile {

   @Asynchronous
   public void showNewFile() throws IOException{
        WatchService watchService = FileSystems.getDefault().newWatchService();        
        WatchKey watchKey = Paths.get("/home/user/input").register(watchService,new WatchEvent.Kind<?>[] { ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE });
        while (true) {
            try {
                watchKey = watchService.take();
            } catch (InterruptedException ex) {
                System.out.println("InterruptedException: " + ex);
            }

            for (WatchEvent<?> watchEvent : watchKey.pollEvents()) {
                System.out.println(watchEvent.kind() + " " + ((Path) watchEvent.context()));
            }
            watchKey.reset();
        }
    }
}

In this class I call the methode:

@Named("startWatcher")
public class StartWatcher {

    private NewFile newFile;

    public void runSearcher() throws IOException{

        newFile.showNewFile();
    }
}

以及你的 index.xhtml 中的相关部分

<h:commandButton actionListener="#{startWatcher.runSearcher()}" value="test"/>

我希望你能理解我的问题,我知道我的英语不是很好。我期待收到提示我做错了什么。

4

1 回答 1

1

通常,您应该在部署 GlassFish 域时通过定义 @WebListener 来启动 watchservice 线程,例如:

import static java.nio.file.StandardWatchEventKinds.*;

import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyServletContextListener implements ServletContextListener {

    private final NewFileRunner runner = new NewFileRunner();

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        runner.startThread();
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        runner.stopThread();
    }

    class NewFileRunner implements Runnable {

        private volatile Thread thread;
        private final WatchService watchService;

        public NewFileRunner() {
            watchService = FileSystems.getDefault().newWatchService();
            Paths.get("/home/user/input").register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
        }

        /**
         * Start a worker thread to listen for directory changes.
         */
        public void startThread() {
            thread = new Thread(this);
            thread.start();
        }

        /**
         * Flag worker thread to stop gracefully.
         */
        public void stopThread() {
            if (thread != null) {
                Thread runningThread = thread;
                thread = null;
                runningThread.interrupt();
            }
        }

        @Override
        public void run() {
            Thread runningThread = Thread.currentThread();
            while (runningThread == thread) {
                WatchKey watchKey = null;
                try {
                    watchKey = watchService.take();
                    if (watchKey != null) {
                        for (WatchEvent<?> watchEvent : watchKey.pollEvents()) {
                            System.out.println(watchEvent.kind() + " " + ((Path) watchEvent.context()));
                        }
                        watchKey.reset();
                    }
                } catch (InterruptedException e) {
                    e = null;
                }
            }
        }

    }
}

当然,我会将其重构为多个类,但这将为您指明正确的方向。

于 2014-04-09T02:36:40.087 回答