Java 将线程排队

Java 将线程排队,java,multithreading,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 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 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 
现在说到这里,当线程1和线程2在
printListOfStrings()
方法中同时运行for循环时,我没有问题。但是线程3与线程A具有相同的字符串列表,不应允许它与线程A一起运行。如果线程A在线程C之前启动,则应允许A在C等待其完成时执行,或者如果线程C在A之前启动,则应允许C在A等待C完成时执行。我应该在我的
printListOfStrings()
方法中添加什么来实现这一点。提前谢谢


注意:我不想在任何地方使用synchronized关键字,因为它没有给线程一个公平的运行机会(即线程的顺序)

您可以编写infinite循环,在其中可以检查t1是否在启动t3之前完成

  while(true){
       if(t1.isAlive){
        Thread.sleep(1000);
       }else{
       t3.start();
       }
  }

如果您使用的是最新版本的java,则可以使用---


线程的启动顺序与此无关。一旦启动,它们将(几乎)同时运行。这就是线程的全部要点

如果希望其中一个线程等待某些内容,则需要调用wait()方法,另一个线程需要在完成时通知()。它们都需要围绕同一个物体同步

因此,在方法顶部创建一个对象:

final Object syncOb = new Object();
在thread1中,在调用PrintListOfstring后添加:

synchronized (syncOb) {
    syncOb.notify();
}
synchronized (syncOb) {
    syncOb.wait();
}
在thread3中,在调用PrintListOfstring之前添加:

synchronized (syncOb) {
    syncOb.notify();
}
synchronized (syncOb) {
    syncOb.wait();
}

其他线程将有相当的机会运行,因为它们不会在syncOb上同步。

很奇怪,您想要同步具有相同列表内容的线程(尽管列表本身不同,这使得@RajSharma answer不正确)。然而,以下是使用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;
    });
}
静态ConcurrentHashMap=新ConcurrentHashMap();
公共静态无效打印列表字符串(集合cs){
map.ComputeFabSent(cs,k->{
用于(字符串str:cs)
System.out.print(str+“by”+Thread.currentThread().getName());
System.out.println();
返回null;
});
}

代码的其余部分是相同的。请注意,
map
始终保持为空,我们从不向其添加元素。但是,当为单个键运行
computeIfAbsent
时,此键将被阻止用于其他操作,但其他键可以同时操作。这里作为
lt1
lt3
列表是相等的,并且具有相同的hashcode,他们的访问是同步的。

您可能想使用锁。您可以在t1之后使用join。start但这将停止t2和t3。您必须使用锁…使用锁会使独立线程B停止谢谢您@Panther。但是您的答案是硬编码的。我希望所有具有相似字符串列表的线程都在一个公平队列中。定义“相似字符串列表”和“公平队列”。我相信您可以实现2-3阻塞队列,将相同类型的线程保持在相同队列中。@kresho如果线程a有{“1”,“2”},线程B有{“3”,“4”},线程C有{“1”,“5”},线程D有{“1”,“6”}我想说线程A、C和D有类似的列表。线程B具有唯一的列表。如果线程是以A、D、C的顺序启动的,那么应该允许它们以相同的顺序执行for循环。应该首先执行。D应该等待A完成。C应该等待D完成。我会称之为,正如你研究过阻塞queuqe一样,它看起来非常简单。
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;
    });
}