基于条件的Java并发

基于条件的Java并发,java,multithreading,Java,Multithreading,创建一个接受整数作为参数的方法,并在控制台上打印。此方法由多个线程访问。如果两个或多个线程使用相同的值调用该方法,则只有一个线程允许打印其他线程应等待的值。如果值不同,则所有线程都应允许打印该值。 我知道在这里实习会有帮助,但Java实习会一直持续到值小于128为止。之后,两个具有相同值的整数是不同的对象。。。能做到吗?是否有条件同步的规定 关于防止多个线程打印相同值,但允许它们打印不同值的要求 防止这种情况的最简单方法是已经打印一组整数。因为您正在打印,所以使用锁的开销很小 Set<I

创建一个接受整数作为参数的方法,并在控制台上打印。此方法由多个线程访问。如果两个或多个线程使用相同的值调用该方法,则只有一个线程允许打印其他线程应等待的值。如果值不同,则所有线程都应允许打印该值。 我知道在这里实习会有帮助,但Java实习会一直持续到值小于128为止。之后,两个具有相同值的整数是不同的对象。。。能做到吗?是否有条件同步的规定

关于防止多个线程打印相同值,但允许它们打印不同值的要求

防止这种情况的最简单方法是已经打印一组整数。因为您正在打印,所以使用锁的开销很小

 Set<Integer> printed = Collections.synchronizedSet(new HashSet<Integer>());

 // when printing
 if (printed.add(num)) // will one be true the first time for each number
     System.out.println("num: " + num);
您不能简单地决定忽略调用者发出的
已同步的

是否有条件同步的规定

最简单的方法是锁定不同的锁或本地线程。锁定无约束对象非常快

e、 g

顺便说一句,这是一件非常奇怪/令人困惑的事情。我会认真考虑改变你的设计,所以这不是必需的。编写普通的多线程代码很难编写/理解。

私有静态最终集lockedIntegers=new HashSet();
private static final Set<Integer> lockedIntegers = new HashSet<>();

private void lock(Integer key) throws InterruptedException {
    synchronized (lockedIntegers) {
        while (!lockedIntegers.add(key)) {
            lockedIntegers.wait();
        }
    }
}

private void unlock(Integer key) {
    synchronized (lockedIntegers) {
        lockedIntegers.remove(key);
        lockedIntegers.notifyAll();
    }
}

public void printEqualIntegersSynchronously(Integer key) throws InterruptedException {
    try {
        lock(key);

        System.out.println(key);
        //Do whatever you need with your key.
        //For different keys this part is executed in parallel.
        //For equal keys this part is executed synchronously.

    } finally {
        unlock(key);
    }
}
私有无效锁(整数密钥)引发InterruptedException{ 同步(带锁整数){ while(!lockedIntegers.add(key)){ 带锁的整数。等等(); } } } 私有无效解锁(整数密钥){ 同步(带锁整数){ 锁具。取下(钥匙); LockedInteger.notifyAll(); } } public void printequalintegers同步(整数键)引发中断异常{ 试一试{ 锁(钥匙); 系统输出打印项次(键); //用钥匙做任何你需要的事。 //对于不同的键,此部分并行执行。 //对于相等的键,这一部分是同步执行的。 }最后{ 解锁(钥匙); } }

最后重试-非常重要-即使操作引发异常,您也必须保证在操作后解锁等待的线程。”System.out.println“很可能永远不会抛出异常-但对于其他实际情况,“try finally”是必需的。顺便说一句,“System.out.println”本身已经同步了,所以对于“System.out.println”来说完全不需要它。

“…其他线程应该等待”直到什么?你没有在某个条件下同步-你在一个对象上同步,然后(在你的情况下)根据该对象的值在同步块内执行逻辑,取决于它是否满足条件。但整个问题的定义非常模糊。例如:如果一个线程调用'4',一分钟后另一个线程调用'4',会发生什么情况?除非你明白(并且能够解释)应该发生什么,否则很难帮助你。每个值只能打印一次吗?如果是,调用线程会发生什么情况?它们会永远阻塞吗?@JVMATL当两个线程调用相同的值时,一个线程应该等待另一个线程完成。简单地说,如果一个线程以值4执行,那么所有试图以值4执行的线程都应该被阻塞。但是,应该允许具有非4值的线程访问syncronized方法。因此,具有相同值的其他线程应该等到当前线程完成。我认为这并不能完全回答他提出的问题(尽管这个问题相当模糊,所以我不能100%确定问了什么…)--这个答案如何解决防止多个线程打印相同值,但允许它们打印不同值的要求?尽管描述很奇怪,但这听起来像是问题的重要部分。@JVMATL您不能同时打印多个线程。System.out已经同步了,您不能轻松地取消同步,您也不想取消同步。我知道System.out是同步的,但从用户的描述来看,不清楚System.out上的同步以防止打印输出交错是他的问题的要点;他似乎在问,如果用“相同的值”调用他的方法,与用不同的值调用他的方法,如何做不同的事情,我只是说,这个答案并没有真正解决这个问题。如果他所关心的只是防止他的指纹交错,那么他为什么还要提到这些值是相同的还是不同的呢?(不,我不知道他想做什么)@JVMATL我回答的第二部分是如何有条件地锁定共享对象。@PeterLawrey假设该函数不打印到控制台。它对该整数执行其他操作。。如前所述,问题的重要部分是“关于防止多个线程打印相同值,但允许它们打印不同值的要求”。。
synchronized(shared ? sharedObject : Thread.currentThread()) {

}
private static final Set<Integer> lockedIntegers = new HashSet<>();

private void lock(Integer key) throws InterruptedException {
    synchronized (lockedIntegers) {
        while (!lockedIntegers.add(key)) {
            lockedIntegers.wait();
        }
    }
}

private void unlock(Integer key) {
    synchronized (lockedIntegers) {
        lockedIntegers.remove(key);
        lockedIntegers.notifyAll();
    }
}

public void printEqualIntegersSynchronously(Integer key) throws InterruptedException {
    try {
        lock(key);

        System.out.println(key);
        //Do whatever you need with your key.
        //For different keys this part is executed in parallel.
        //For equal keys this part is executed synchronously.

    } finally {
        unlock(key);
    }
}