基于条件的Java并发

时间:2014-01-17 15:35:39

标签: java multithreading

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

2 个答案:

答案 0 :(得分:1)

  

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

防止这种情况的最简单方法是打印一组整数。由于您正在打印使用锁定的开销很简单。

 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。来自PrintStream,它实现了System.out和err

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

您不能简单地决定忽略来自调用者的synchronized

  

条件同步的任何规定??

最简单的方法是锁定不同的锁或本地线程。锁定一个没有条件的对象非常快。

e.g。

synchronized(shared ? sharedObject : Thread.currentThread()) {

}
BTW这是非常奇怪/令人困惑的事情。我会认真考虑改变你的设计,所以这不是必需的。编写正常的多线程代码很难写入/理解。

答案 1 :(得分:0)

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);
    }
}

最终尝试-非常重要-即使操作引发异常,也必须保证在操作后解锁等待线程。 'System.out.println'很可能永远不会抛出异常-但是在其他实际情况下,“最终尝试”是强制性的。顺便说一下,“ System.out.println”已经被自己同步了,因此对于“ System.out.println”来说就不需要了。