如何在使用java.text.Collat​​or进行并发排序时避免线程阻塞?

时间:2016-03-21 15:59:07

标签: java multithreading sorting

当我的服务器负载很重时,java.text.RuleBasedCollator.getCollationKey()中的线程阻塞问题。

以下是出现问题的类:

public class DefaultFacetDisplayNameComparator implements Comparator
{
    private final Collator trTRCollator = Collator.getInstance(new Locale("tr", "TR"));

    @Override
    public int compare(final FacetValue value1, final FacetValue value2)
    {
        if (!StringUtils.isEmpty(value1.getDisplayName()) && !StringUtils.isEmpty(value2.getDisplayName()))
        {
            //KOTT-672
            final CollationKey displayName1 = trTRCollator.getCollationKey(value1.getDisplayName());
            final CollationKey displayName2 = trTRCollator.getCollationKey(value2.getDisplayName());
            return displayName1.compareTo(displayName2);
        }
        else if (!StringUtils.isEmpty(value1.getName()) && !StringUtils.isEmpty(value2.getName()))
        {
            //KOTT-672
            final CollationKey name1 = trTRCollator.getCollationKey(value1.getName());
            final CollationKey name2 = trTRCollator.getCollationKey(value2.getName());
            return name1.compareTo(name2);
        }
        else
        {
            return 0;
        }
    }

以下是来自线程转储的片段,显示了有问题的阻塞:

  

" xxxHTTP227" prio = 5 tid = 0x355 nid = 0x163 BLOCKED拥有   hybrisHTTP109 Id = 236 - stats:cpu = 339 blk = -1 wait = -1   java.lang.Thread.State:BLOCKED at   java.text.RuleBasedCollat​​or.getCollat​​ionKey(RuleBasedCollat​​or.java:597)      - 等待在com.core.commercesearch.search.solrfacetsearch.comparators.DefaultFacetDisplayNameComparator.compare(DefaultFacetDisplayNameComparator.java:27)中锁定java.text.RuleBasedCollat​​or@1b9f75ac     在   de.hybris.platform.solrfacetsearch.search.impl.comparators.FacetDisplayNameComparator.compare(FacetDisplayNameComparator.java:1)     在java.util.TimSort.binarySort(TimSort.java:265)at   java.util.TimSort.sort(TimSort.java:190)at   java.util.TimSort.sort(TimSort.java:173)at   java.util.Arrays.sort(Arrays.java:659)at   java.util.Collections.sort(Collections.java:217)at   de.hybris.platform.solrfacetsearch.search.impl.DefaultFacetSearchService.sortFacetValues(DefaultFacetSearchService.java:444)     在   de.hybris.platform.solrfacetsearch.search.impl.DefaultFacetSearchService.convertResponse(DefaultFacetSearchService.java:268)     在   de.hybris.platform.solrfacetsearch.search.impl.DefaultFacetSearchService.queryInternal(DefaultFacetSearchService.java:194)     在   de.hybris.platform.solrfacetsearch.search.impl.DefaultFacetSearchService.search(DefaultFacetSearchService.java:125)     在   de.hybris.platform.commerceservices.search.solrfacetsearch.populators.SolrSearchRequestResponsePopulator.populate(SolrSearchRequestResponsePopulator.java:68)     在   de.hybris.platform.commerceservices.search.solrfacetsearch.populators.SolrSearchRequestResponsePopulator.populate(SolrSearchRequestResponsePopulator.java:1)     在   de.hybris.platform.converters.impl.AbstractPopulatingConverter.populate(AbstractPopulatingConverter.java:61)     在   de.hybris.platform.commerceservices.converter.impl.AbstractPopulatingConverter.convert(AbstractPopulatingConverter.java:40)     在   de.hybris.platform.commerceservices.search.solrfacetsearch.impl.DefaultSolrProductSearchService.doSearch(DefaultSolrProductSearchService.java:127)     在   de.hybris.platform.commerceservices.search.solrfacetsearch.impl.DefaultSolrProductSearchService.searchAgain(DefaultSolrProductSearchService.java:111)     在   de.hybris.platform.commerceservices.search.solrfacetsearch.impl.DefaultSolrProductSearchService.searchAgain(DefaultSolrProductSearchService.java:1)     在   de.hybris.platform.commercefacades.search.solrfacetsearch.impl.DefaultSolrProductSearchFacade $ 4.execute(DefaultSolrProductSearchFacade.java:184)     在   de.hybris.platform.commercefacades.search.solrfacetsearch.impl.DefaultSolrProductSearchFacade $ 4.execute(DefaultSolrProductSearchFacade.java:1)     在   de.hybris.platform.commerceservices.threadcontext.impl.DefaultThreadContextService.executeInContext(DefaultThreadContextService.java:54)     在   de.hybris.platform.commercefacades.search.solrfacetsearch.impl.DefaultSolrProductSearchFacade.categorySearch(DefaultSolrProductSearchFacade.java:177)     在   com.acme.storefront.controllers.pages.CategoryPageController $ CategorySearchEvaluator.doSearch(CategoryPageController.java:918)

如果线程转储显示它们正在执行,我如何避免我的服务器线程阻塞?

2 个答案:

答案 0 :(得分:2)

我不会猜到任何Collator的{​​{1}}实现都需要同步,但这就是线程转储似乎正在显示的内容。从问题中不清楚,但我倾向于认为,虽然当多个线程共享一个getCollationKey()时,这可能您的应用程序,但它不会使它们死锁。

但是,无论哪种方式,最好的解决方案可能是每个线程使用自己的Collator实例,最好的方法可能是每个线程都有自己的主机类实例, Collator

这确实假设DefaultFacetDisplayNameComparator每次调用时都会返回一个不同的Collator.getInstance()实例。如果您发现它在不同的调用中由不同的线程返回相同的实例,并且该实例存在同步问题,那么首先提交错误报告;第二,使用不同的技术获取Collator s(可能直接建立适当的Collator)。

答案 1 :(得分:0)

当我在我的情况下摆脱Collat​​or类使用时,如下所示,似乎我可以防止阻塞线程,所以它就像一个魅力!

private static final String TRtr_ALPHABET = "0123456789AaBbCcÇçDdEeFfGgĞğHhIıİiJjKkLlMmNnOoÖöPpQqRrSsŞşTtUuÜüVvWwXxYyZz";

@Override
public int compare(final FacetValue facetValue1, final FacetValue facetValue2)
{
    String value1 = null;
    String value2 = null;

    if (!StringUtils.isEmpty(facetValue1.getDisplayName()) && !StringUtils.isEmpty(facetValue2.getDisplayName()))
    {
        value1 = facetValue1.getDisplayName();
        value2 = facetValue2.getDisplayName();
    }
    else if (!StringUtils.isEmpty(facetValue1.getName()) && !StringUtils.isEmpty(facetValue2.getName()))
    {
        value1 = facetValue1.getName();
        value2 = facetValue2.getName();
    }
    else
    {
        return 0;
    }

    final int length = Math.min(value1.length(), value2.length());
    int i = 0;
    while ((i < length) && (value1.charAt(i) == value2.charAt(i)))
    {
        i++;
    }
    if (i == length)
    {
        return 0;
    }
    if (TRtr_ALPHABET.indexOf(value1.charAt(i)) < TRtr_ALPHABET.indexOf(value2.charAt(i)))
    {
        return -1;
    }
    return 1;
}