问题描述
我目前正在创建一个推特机器人.
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 ofExecutorService
(please note thatExecutorService
is an interface). - Now in case of
newCachedThreadPool()
,newFixedThreadPool(int nThreads)
you will get an object ofThreadPoolExecutor
(please note thatThreadPoolExecutor
implementsExecutorService
interface). - When you do
Executors.newFixedThreadPool(2);
, you only get an object ofThreadPoolExecutor
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 inLinkedBlockingQueue
implementation, and sinceLinkedBlockingQueue
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 withcorePoolSize
of let say 100 and setmaximumPoolSize
asInteger.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());
}
这篇关于如何在多线程应用程序中存储线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!