有没有一种方法可以在Java中将一个方法声明为新线程?

3
我有一个程序在监听随机数。它连接到一个发布者,每次更新时给我一个数字和一个新的计数,并将该数字的当前计数存储在HashMap中。
我还有一个SSL服务器在监听请求。当收到一个请求询问“我们有多少个7”,我只需返回HashMap中的值。
现在我想添加逻辑,如果该数字出现0次,则等待直到该数字出现一次,并在那时返回计数。然而,由于Thread的run方法的限制必须是void类型,所以我很困惑。我想知道是否有任何方法可以将我的方法声明为始终启动新线程的方法,或者是否有更好的处理方法比我正在做的更好。以下是我的代码:
private static volatile HashMap<Integer, Integer> occurenceMap= new HashMap<Integer, Integer>();

public synchronized static int getNumOccurrences(final Integer number) {

    try { 
    (new Thread() {

        public void run() {

            Integer occurrences = occurenceMap.get(number); 
            if ( occurrences != null && occurrences > 0 ) {
              // here I would like to just return occurences;
            } else {
                CountDownLatch latch = new CountDownLatch(1); 
                pendingList.put(number, latch);
                latch.await();  
                // elsewhere in the code, I call countdown when I get a hit
                pendingList.remove(number);

                // once we've counted down, I would like to return the value
             }
           }
       }).start();
   } catch ( Throwable t ) { }
}

然而,我不能在run方法中使用返回语句。那么这怎样做最好呢?

谢谢!

2个回答

0
你需要某种外部结构来存储数字,就像这样。
// declared outside your runnable
final AtomicInteger result = new AtomicInteger(0);

// in your run method
// return value; // doesn't work, can't return
result.set(value);

因此将其添加到您的代码中,您会得到这个结果

请注意我的注释以// C:开头

private static volatile HashMap<Integer, Integer> occurenceMap= new HashMap<Integer, Integer>();


    public synchronized static int getNumOccurrences(final Integer number) {
        // C: here's a container to use inside the runnable
        // C: must be final to use inside the runnable below
        final AtomicInteger result = new AtomicInteger(0);
        try { 
        // C: keep a rerefence to the thread we create
        Thread thread = new Thread() {

            public void run() {

                Integer occurrences = occurenceMap.get(number); 
                if ( occurrences != null && occurrences > 0 ) {
                    result.set(occurences); // C: we found what we're looking for
                    return; // C: so get out of the run method
                } else {
                    CountDownLatch latch = new CountDownLatch(1); 
                    pendingList.put(number, latch);
                    latch.await();  
                    // elsewhere in the code, I call countdown when I get a hit
                    pendingList.remove(number);

                    // once we've counted down, I would like to return the value
                    result.set(1); // C: I'm not sure what you want to return here
                    return; // C: but I'm sure you can figure that out...
                 }
               }
           });
           thread.start(); // C: now start the thread
           thread.join(); // C: join the thread, waiting for it to finish
       } catch ( Throwable t ) { }
       return result.get(); // C: now return the int from the container
    }

好的,明白了,谢谢。不过,我想我需要一种列表数据结构,以防我们等待超过一个请求 - 比如有人请求44523,另一个用户请求12,所以我们可能需要等待多个请求。我的大部分经验都是单线程编程,所以如果这是一个愚蠢的问题,我很抱歉,但为什么在这种情况下我需要使用thread.join()呢? - sally
如果你不使用 join,那么在线程完成之前,你的方法很快就会退出。这样它每次都会返回 0,只有在线程最终完成后才会被更新,而此时你的方法已经完成了。你需要在调用该方法的地方创建一个列表,但是你不需要在内部创建一个列表。每次方法调用都会创建一个新的线程,而不是重复使用同一个线程。 - corsiKa
我本以为倒计时门闩会强制等待,这样方法就不会退出了。不是吗?谢谢你的帮助。 - sally
倒计时门闩强制线程比方法花费更长的时间。join 强制方法说“在返回之前等待此线程完成”。 - corsiKa
我明白了。它会将其加入到主线程还是调用它的线程?我有我的主线程正在处理监听器部分,然后另一个线程在套接字上等待客户端请求。正在等待客户端请求的那个线程将实际激活此方法,并且我想将其加入到该线程。这就是join的工作方式吗? - sally

0

从你的Thread执行中返回值的另一种方法是使用Executors线程池,它允许您提交一个Callable

// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (Job job : jobsToDo) {
    futures.add(threadPool.submit(new Callable<Integer>() {
       public Integer call() {
          ...
       }
     }));
}
// after submitting the jobs, you need to shutdown the queue
threadPool.shutdown();
// then you can get the results
for (Future<Integer> future : futures) {
    // this will throw if your call method throws
    int value = future.get();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接