多线程的良好实践

时间:2012-03-21 01:31:06

标签: java android multithreading thread-safety

我有一个应用程序,当一个"游戏"统计数据,它启动了几个不同的线程。我开始这样的线程:

Thread thread = new Thread(new Runnable()
{
    public void run()
    {
        //...
    }
});

thread.setName("killMeAtEnd");
thread.start();

稍后当游戏结束时,我在游戏内部有一个dispose()方法,该方法对所有正在运行的线程进行排序,并结束所有具有名称" killMeAtEnd"的线程。我的问题是,这是一个好习惯吗?我的目的是保持我的应用程序快速运行和杂乱无章,根据我的经验,留下的线程"悬挂"在应用程序终止之前,往往会放慢手机的速度。有一个更好的方法吗?这甚至值得打扰吗?

修改

如果有人有兴趣,这是我的dispose()。此代码属于Game类。

public void dispose()
{
    Thread threads[] = (Thread[])Thread.getAllStackTraces().keySet().toArray();
    for(int x=0;x<threads.length;x++)
    {
        Thread thread = threads[x];
        if(thread.getName().equalsIgnoreCase(KILL))
        {
            try
            {
                thread.interrupt();
            }catch(Exception e){Log.e(Viewer.GAME,Log.getStackTraceString(e));}
            thread = null;
        }
    }
}

public static final String KILL = "endOnDispose";

3 个答案:

答案 0 :(得分:4)

你有正确的想法,但有一些方面需要改进:

  1. 只需在创建线程时将线程添加到列表中,而不是查询系统中所有正在运行的线程。然后,您可以终止您创建的所有线程或等待它们完成(加入)。
  2. 中断只会中断处于阻塞状态的线程,因此您需要有一个额外的标志,线程会定期检查(即每个“工作周期”之后)。
  3. 在线程中捕获中断异常并处理它(即正常退出)。

答案 1 :(得分:3)

这不是必然一个糟糕的解决方案,但存在一些问题:

  • 如果你的线程是处理一个任务完成的排序的工作线程,那么线程可能会有更好的设计结束。换句话说,可能有更好的执行流程,不需要在最后被杀死。

  • 当你说“对所有正在运行的线程进行排序......”时,我想你正在查看JVM中所有正在运行的线程?就像this SO question中的某些内容一样?如果是这种情况,为什么不只是保留对游戏所拥有的所有线程的引用,然后专门杀死它们?而不只是寻找“killMeAtEnd”;我无法想到你的策略会出现什么问题,但跟踪你的线程似乎更清晰。

保持线程清洁绝对是一种好习惯。如果你的线程正在做一些不那么具体的任务导向(例如,等待网络io,或者某些东西),那么我的第一个建议就有点无关紧要了。我建议你仔细考虑如何保持线程干净,因为线程错误可能会很大。

答案 2 :(得分:0)

已经存在类ExecutorService来处理这类问题。

为ExecutorService创建所有线程任务。

当游戏结束时,使用shutdownNow关闭ExecutorService。这将中断ExecutorService中所有线程的中断。然后,您可以在开始新游戏时创建新的ExecutorService。

如果修复了线程数,可以使用Executors.newFixedThreadPool()创建ExecutorService。

如果线程数是可变的,您可以使用Executors.newCachedThreadPool来创建ExecutorService。