java - 排队线程

标签 java multithreading

考虑以下代码

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 

第二次运行:

   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 

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

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

最佳答案

您想要同步具有相同列表内容 的线程是很奇怪的(尽管列表本身不同,这使得@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 列表是相等的并且具有相同的哈希码,所以它们的访问是同步的。

关于java - 排队线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32244941/

相关文章:

java - 我应该如何在 Java 中表示依赖关系图?

java - 从 java 导入 MySQL DB 不起作用

c# - 多线程锁定/监控

python - 在多线程时以编程方式退出 python 脚本

c++ - 在C++中使用std::thread和std::condition_variable进行自定义后台任务的SIGABRT

java - 这是什么服务器端编程语言?

java - SpringBoot - 完全停用安全性以启用摘要转发

java - Android 的 Java 中的 PerformSelectorOnMainThread 等效项

java - Java 套接字是否支持全双工?

Javac Ant 构建错误