【问题标题】:I have "Interrupted while waiting on semaphore" when I'm using ThreadManager and ChannelService in Google App Engine Javaservlet当我在 Google App Engine Javaservlet 中使用 ThreadManager 和 ChannelService 时出现“等待信号量时中断”
【发布时间】:2015-12-19 11:13:50
【问题描述】:

我想通过ChannelService.sendMessageThreadManager.createThreadForCurrentRequest 可运行方法中发送消息。但是当我在 doGet 中调用此方法时,我在码头记录器中有一条错误消息。 这是我在 HttpServlet 类中的代码:

    @Override
public void  doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    name = req.getParameter("name");
    ThreadManager.createThreadForCurrentRequest(new Runnable() {
        @Override
        public void run() {
            for (int i = 10; i < 100; i++) {
                d = com.google.appengine.repackaged.org.joda.time.DateTime.now();
                serverTime = String.valueOf(d.getMillis());
                ChannelMessage channelMessage = new ChannelMessage("logger", i+ " Message..... " + name + " Server Time: " + serverTime + " Client Time:");
                getChannelService().sendMessage(channelMessage);

            }

        }
    }).start();

}

这是码头记录器中的错误:

Exception in thread "Thread-12" java.lang.RuntimeException: Interrupted while waiting on semaphore:
at com.google.appengine.tools.development.ApiProxyLocalImpl.makeAsyncCall(ApiProxyLocalImpl.java:193)
at com.google.appengine.tools.development.ApiProxyLocalImpl.makeSyncCall(ApiProxyLocalImpl.java:156)
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:118)
at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:67)
at com.google.appengine.api.channel.ChannelServiceImpl.sendMessage(ChannelServiceImpl.java:85)
at com.roundtableapps.pluto.backend.MyServlet$1.run(MyServlet.java:42)
at com.google.appengine.tools.development.RequestThreadFactory$1$1$2.run(RequestThreadFactory.java:110)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.appengine.tools.development.RequestThreadFactory$1$1.run(RequestThreadFactory.java:107)
Caused by: java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1301)
    at java.util.concurrent.Semaphore.acquire(Semaphore.java:317)
    at com.google.appengine.tools.development.ApiProxyLocalImpl.makeAsyncCall(ApiProxyLocalImpl.java:190)
    ... 8 more

我该如何解决这个问题?

【问题讨论】:

    标签: java google-app-engine servlets


    【解决方案1】:

    ThreadManager.createThreadForCurrentRequest 线程将在请求后停止(中断)。在退出doGet 方法之前,您必须在那里等待,直到它完成。

    所以基本上这样的线程没有任何意义。此外,您在同一个线程中完成所有艰苦的工作(我的意思是循环块),而不是并行化它。

    类似这样的:

    @Override
    public void  doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        name = req.getParameter("name");
        List<Future> waits = new ArrayList<>(90);
        ExecutorService executors = Executors.newFixedThreadPool(50, ThreadManager.currentRequestThreadFactory());
        for (int i = 10; i < 100; i++) {
           waits.add(executors.submit(new Callable<Boolean>() {
               Boolean call() { 
                    d = com.google.appengine.repackaged.org.joda.time.DateTime.now();
                    serverTime = String.valueOf(d.getMillis());
                    ChannelMessage channelMessage = new ChannelMessage("logger", i+ " Message..... " + name + " Server Time: " + serverTime + " Client Time:");
                    getChannelService().sendMessage(channelMessage);
                    return true;
                }
    
            }))
        }
        for (Future f: waits) {
           f.get()
        }
    
    }
    

    如果你只需要一个线程,那么所有与线程相关的部分都可以去掉:

    @Override
    public void  doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
        name = req.getParameter("name");
        for (int i = 10; i < 100; i++) {
            d = com.google.appengine.repackaged.org.joda.time.DateTime.now();
            serverTime = String.valueOf(d.getMillis());
            ChannelMessage channelMessage = new ChannelMessage("logger", i+ " Message..... " + name + " Server Time: " + serverTime + " Client Time:");
            getChannelService().sendMessage(channelMessage);
        }
    }
    

    【讨论】:

    • 好的!那么,你在线程中做某事的解决方案是什么?
    • Call 方法的返回值是多少?
    • 任何事情,我想这对你来说没关系
    • 好的,它有效。但我有一个问题。 Executor.newFixedThreadPool 会创建 50 个或更多线程吗?因为在这种情况下我只需要一个线程。
    • 50。有一个线程有什么意义?对于一个线程,你不需要使用 ThreadManager,你已经有当前线程,只需在主线程中做所有事情,删除所有与多线程相关的代码
    猜你喜欢
    • 1970-01-01
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多