2012-10-23 32 views
-2

我有一个类需要提供快速分类服务。例如,我想编写类似“classify(”Ac Kd Kh 3c 3s“)”的代码,它很快返回TWO_PAIR。 (这不是应用程序,但你得到了jist)静态initalizer块中的多线程代码产生死锁

因为我需要快速的分类我想预先计算,然后存储一个查找表,列出所有可能的输入的分类输出。为了时间的利益,我希望将这个预计算并行化。但是,试图从第二个线程使用“classifySlowly”会造成死锁。

public class Classifcation Service { 
    enum CLASS {TYPE_A, TYPE_B, ...}; 

    static CLASS[] preComputedClassLookUpTable; 

    static { 
    preComputedClassLookUpTable = constructLookUpTableInParallel(); 
    } 

    //Note: using this method from with constructLookUpTableInParallel causes deadlock 
    private static CLASS classifySlowly(Object classifyMe) { 
    //do time intensive work to classify the input 
    // -- uses no other methods from this class 
    return classification; 
    } 

    public static CLASS classify(Object classifyMe) { 
    //use the lookup table to do a quick classification 
    return classification; 
    } 
} 

所以我的问题是:有没有一种方法来预先计算静态initalizer块内的并行查找表?

唯一的(差)替代我看到的是切换从:

preComputedClassLookUpTable = constructLookUpTableInParallel(); 

要:

preComputeClassLookUpTable = loadLookUpTableFromFile(); 
if(preComputedClassLookUpTable == null) { 
    System.out.println("WARNING: Construction incomplete, Must call computeAndSaveLookUpTableFile();} 
} 

我想这将是太多,但这里是constructLookUpTableInParallel实施

private static CLASS[] constructLookUpTableInParallel() { 

    //build a collection of Runnables by iterating over all possible input Objects 
    //wrap each possible input in an anonymous Runnable that calls classifySlowly. 

    //submit the collection of Runnables to a new ExecutorService 
    //process runnables... 
    //shutdown executor service  
} 

////////底部原文问题结束///////////

解决方案的工作原理有点干净,就是将classifySlowly(Object classifyMe)和classify(Object classifyMe)方法分成两个不同的类。

这将允许包含“public static CLASS classifySlowly(Object classifyMe)”的(第一个)类在包含“public static CLASS classifyQuickly(Object classifyMe)”的(second)类需要的时候完全加载使用classifySlowly方法。现在,第二个静态初始化块不需要任何自己的静态方法,它可以完全并行化。

+2

这是相当困难的调试多线程代码时,你不要张贴多线程代码。什么是'constructLookUpTableInParallel'在做什么? –

+0

你怎么知道它的僵局?为什么'loadLookUpTableFromFile'糟糕的选择?预先计算并存储在文件中可能是一个好主意,以便更快地初始化 –

+0

@JohnB - 它隐藏了复杂性。如果constructLookUpTableInParallel没有启动新的线程,程序会正常工作。但是,如果您必须知道,它会创建一组Runnables来执行每个分类任务,然后将这些Runnables提交给ExecutorService – Ivan

回答

0

“所以我的问题是:有没有办法从静态initalizer块内预先计算这个查找表在并行?”

是的,实际上肯定有一种方法。只需新建数组并为每个数组元素启动一个Runnable。将每个Runnable引用赋予该数组,并为其计算索引,然后让它在不锁定的情况下执行计算,然后在将结果分配给数组元素时进行锁定。

注意/免责声明:这个答案是基于这个问题给出的相当不完整的信息...

+0

我尝试了一些非常相似的东西,它doesn不起作用,因为runnables无法访问classifySlowly,直到静态初始化块完成后。 – Ivan

+1

因此,改变顺序或分割静态初始化块,或者甚至将它分割成多个类。为什么分类只需要在同一个班级中? – hyde

+0

为了简单起见,我希望在同一个班级中拥有一切。我会尝试使用这个解决方案有两个不同的静态无弹性块...但我想我已经尝试过了。 – Ivan