如何在多线程应用程序中存储线程

时间:2017-04-26 14:26:38

标签: java android multithreading

我现在正在创建一个Twitter机器人。

我有一个侦听器正在侦听包含某个标签的状态 - #DealMeIn。当使用此主题标签找到状态时,我有一个方法可以创建一个新的线程来玩游戏:

public void onTweet() {
  Thread t = new Thread(new Game());
  t.start();
}

如果我没有弄错的话,上述方法的问题是,每次发现推文都会覆盖t。所以,我认为合适的替代方案是使用ArrayList<Thread> threads

public void onTweet() {
  threads.add(new Thread(new Game()));
  threads.get(threads.size()-1).start();
}

这是处理我的线程的合适方式吗?

编辑:如果用户推文,例如#DealMeOut,那么我需要能够停止该线程。

2 个答案:

答案 0 :(得分:2)

@Michael给出的答案很好,但我更愿意通过使用Java executor service来完成这项工作,因为它提供了更多的控制,优雅的方式来做到这一点,那是什么Java提供了API来处理这种情况。

见下面的代码示例。这种方法的明显优势在于您可以控制在JVM中运行的最大线程数,这非常重要,否则在应用程序可能开始计时的一段时间内,因此这样可以提供更高的可伸缩性到您的应用程序/解决方案

如果您不了解Java的执行程序服务,那么下面的几个快速点可以帮助您入门:

  • Java的实用工具类Executors将创建并返回ExecutorService的对象(请注意ExecutorService是一个接口)。
  • 现在,如果是newCachedThreadPool()newFixedThreadPool(int nThreads),您将获得ThreadPoolExecutor的对象(请注意ThreadPoolExecutor实现ExecutorService接口。)
  • 执行Executors.newFixedThreadPool(2);时,只会获得ThreadPoolExecutor的对象,其中包含所有实例变量,如核心池大小,最大池大小等设置,在您的情况下,它将设置为2。
  • 现在,使用private final static ExecutorService executorService = Executors.newFixedThreadPool(2);,您的JVM中将始终为此线程池提供最多2个线程,并且任何多余的请求将在LinkedBlockingQueue实现中排队,并且LinkedBlockingQueue是一个无限制的队列,所以你永远不会失去你的任务。
  • 假设您想要在有更多负载时创建更多线程,那么您必须使用maximumPoolSize并使用有界队列。因此,根据您的系统容量/应用程序负载,您可以从corePoolSize开始,比如100,并将maximumPoolSize设置为Integer.MAX_VALUE
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceImplementationExample {
    private final static int MAX_NUMBER_OF_THREADS = Integer.MAX_VALUE;

    // set maximum number of threads as per your requirement/performance tuning, for testing set it to "2" and to have better feel.
    private final static ExecutorService executorService = Executors.newFixedThreadPool(MAX_NUMBER_OF_THREADS);


    public static void main(String[] args) {
        System.out.println("### Starting.");

        new Thread(){
            @Override
            public void run() {
                scheduleTask(new MyRunnableTask());
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                scheduleTask(new MyRunnableTask());
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                scheduleTask(new MyRunnableTask());
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                scheduleTask(new MyRunnableTask());
            }
        }.start();

        System.out.println("### Completed.");
    }

    private static void scheduleTask(Runnable runnable) {
        executorService.execute(runnable);
    }

}

MyRunnableTask.java

public class MyRunnableTask implements Runnable {

    @Override
    public void run() {
        System.out.println("I am getting executed: " + this.hashCode() + " | " + Thread.currentThread().getId());
        try {
            Thread.sleep(2000); // this sleep is only for testing to give a feel of how solution will work, remove after testing.
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

在您的情况下,您将执行以下操作,并且您需要在开始时创建executorService,并且您的Game类应实现Runnable界面。

public void onTweet() {
  executorService.execute(new Game());
}

答案 1 :(得分:0)

我会创建一个用户地图到他们的游戏正在进行的线程。

private Map<String, Thread> games = new HashMap<>();

public void onTweet(String user) {
    if (!games.containsKey(user)) // if they haven't got a game running
    {
        Thread t = new Thread(new Game());
        t.start();
        games.put(user, t);
    }
}

public void onStop(String user) {
    if (games.containsKey(user))
    {
        games.remove(user).interrupt();
    }
    else
    {
        //should we handle this?
    }
}

您需要确保线程准备好处理中断。