我现在正在创建一个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,那么我需要能够停止该线程。
答案 0 :(得分:2)
@Michael给出的答案很好,但我更愿意通过使用Java executor service来完成这项工作,因为它提供了更多的控制,优雅的方式来做到这一点,那是什么Java提供了API来处理这种情况。
见下面的代码示例。这种方法的明显优势在于您可以控制在JVM中运行的最大线程数,这非常重要,否则在应用程序可能开始计时的一段时间内,因此这样可以提供更高的可伸缩性到您的应用程序/解决方案。
如果您不了解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?
}
}
您需要确保线程准备好处理中断。