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