排队线程

时间:2015-08-27 08:59:54

标签: java multithreading

考虑以下代码

<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TabWidget
        android:id="@android:id/tabs"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </FrameLayout>
  </LinearLayout>

</TabHost>

第一次运行的代码输出:

public class TestThreads {
    public static void printListOfStrings(Collection<String> cs) {

        for (String str : cs)
            System.out.print(str + " by " + Thread.currentThread().getName());
        System.out.println();
    }

    public static void main(String[] args) {

        final List<String> lt1 = new ArrayList<>();
        for (int i = 0; i < 5; i++)
            lt1.add("string 1");
        Thread thread1 = new Thread(" ONE ") {
            @Override
            public void run() {
                printListOfStrings(lt1);
            }
        };
        thread1.start();

        final List<String> lt2 = new ArrayList<>();
        for (int i = 0; i < 5; i++)
            lt2.add("string 2");
        Thread thread2 = new Thread(" TWO ") {
            @Override
            public void run() {
                printListOfStrings(lt2);
            }

        };
        thread2.start();

        final List<String> lt3 = new ArrayList<>();
        for (int i = 0; i < 5; i++)
            lt3.add("string 1");
        Thread thread3 = new Thread(" THREE ") {
            @Override
            public void run() {
                printListOfStrings(lt3);
            }

        };
        thread3.start();

    }
}

第二次运行:

string 1 by  ONE string 1 by  ONE string 1 by  ONE string 1 by  ONE string 2 by  TWO string 1 by  ONE string 1 by  THREE 
string 2 by  TWO string 2 by  TWO string 2 by  TWO string 2 by  TWO 

现在谈到这一点,当Thread ONE和Thread TWO同时在 string 2 by TWO string 1 by THREE string 1 by ONE string 1 by THREE string 2 by TWO string 1 by THREE string 1 by ONE string 1 by THREE string 2 by TWO string 1 by THREE string 1 by ONE string 2 by TWO string 2 by TWO string 1 by ONE string 1 by ONE string 1 by THREE string 1 by THREE string 1 by THREE string 1 by THREE 方法中运行for循环时,我没有问题。但是,与线程A具有相同字符串列表的Thread THREE不应该与线程A一起运行。如果线程A在线程C之前启动,则应该允许A在C等待它完成时执行,或者如果线程C是在A之前启动,应该允许C执行而A等待C完成。我应该在printListOfStrings()方法中添加什么来实现这一点。提前谢谢。

P.S:我不想在任何地方使用同步关键字,因为它没有给予线程公平的运行机会(即按线程顺序)

1 个答案:

答案 0 :(得分:1)

你想要同步具有相同列表内容的线程是很奇怪的(尽管列表本身是不同的,这使得@RajSharma回答不正确)。然而,这是Java-8 ConcurrentHashMap

解决问题的方法
static ConcurrentHashMap<Collection<String>, Void> map = new ConcurrentHashMap<>();

public static void printListOfStrings(Collection<String> cs) {
    map.computeIfAbsent(cs, k -> {
        for (String str : cs)
            System.out.print(str + " by " + Thread.currentThread().getName());
        System.out.println();
        return null;
    });
}

其余代码是相同的。请注意,map始终为空,我们从不向其添加元素。但是,当computeIfAbsent针对单个密钥运行时,此密钥将被阻止用于其他操作,但其他密钥可以同时运行。这里lt1lt3列表相同并且具有相同的哈希码,因此它们的访问权限是同步的。

相关问题