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

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

本文介绍了如何在多线程应用程序中存储线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在创建一个推特机器人.

I'm creating a twitter bot at the moment.

我有一个监听器监听包含特定主题标签的状态 - #DealMeIn.当找到带有此主题标签的状态时,我有一个方法可以创建一个新线程来玩游戏:

I have a listener listening for a status that contains a certain hashtag - #DealMeIn. When a status is found with this hashtag, I have a method that creates a new thread, that plays a game:

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

上述方法的问题,如果我没记错的话,就是每次找到tweet时t都会被覆盖.所以,我认为一个合适的替代方法是使用 ArrayList线程如下:

The problem with the above method, if I'm not mistaken, is that t will be overwritten each time a tweet is found. So, I'm thinking a suitable alternative would be to use an ArrayList<Thread> threads as such:

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

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

Is this a suitable way to handle my threads?

如果用户发推文,例如,#DealMeOut 那么我需要能够停止线程.

If a user tweets, for instance, #DealMeOut then I need to be able to stop the thread.

推荐答案

@Michael 给出的答案很好,但我更愿意使用 Java 的 executor service,因为它提供了更多的控制,优雅的方式来做到这一点,这就是 Java 提供的 API 来处理遇到这种情况.

Answer given by @Michael is fine but I would prefer to get this job done by using Java's executor service, because it gives more control, elegant way to do this and that's what Java provided API to deal with these kind of situations.

见下面的代码示例.这种方法的明显优势是您可以控制在 JVM 中运行的最大线程数,这非常重要,否则随着时间的推移,您的应用程序可能会开始计时,因此这提供了更多的可扩展性到您的应用程序/解决方案.

See below code example. Clear advantage of this approach is that you can control maximum number of threads running in your JVM, which is extremely important otherwise over period of time your application may start clocking, so this is gives more scalability to your application/solution.

如果您不了解 Java 的 executor 服务,那么以下是一些可以帮助您入门的快速要点:

If you are not aware of Java's executor service then below are few quick points to get you started:

  • 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.立>
  • Java's utility class Executors will create and return objects of ExecutorService (please note that ExecutorService is an interface).
  • Now in case of newCachedThreadPool(), newFixedThreadPool(int nThreads) you will get an object of ThreadPoolExecutor (please note that ThreadPoolExecutor implements ExecutorService interface).
  • When you do Executors.newFixedThreadPool(2);, you only get an object of ThreadPoolExecutor with all instance variables like core pool size, max pool size etc. set, and in your case it will be set to 2.
  • Now, with private final static ExecutorService executorService = Executors.newFixedThreadPool(2); you will always have max of 2 threads in your JVM for this thread pool, and any excess request will get queued up in LinkedBlockingQueue implementation, and since LinkedBlockingQueue is a unbounded queue so you will never loose your task.
  • Suppose you want to create more threads when you have more load then you have to play around with maximumPoolSize and use a bounded queue. So, depending on your system capacity / application load you can start with corePoolSize of let say 100 and set maximumPoolSize as 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 界面.


In your case you will do something like below, and you need to have executorService created in the start and your Game class should implement Runnable interface.

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

这篇关于如何在多线程应用程序中存储线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 01:43