在 ExecutorService 中使用同步块
Using synchronized block in ExecutorService
我有以下代码片段:
public class Service<T> {
private ConcurrentMap<Integer, Integer> locks = new ConcurrentHashMap<Integer, Integer>();
public final ExecutorService exec = Executors.newFixedThreadPool(5);
public Future<Boolean> foo(T o, String fileName) throws IOException {
return exec.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws IOException {
File f = new File(fileName);
// synchronized (getCacheSyncObject(name.hashCode())) {
// try (OutputStream out = new FileOutputStream(f)) {
// //some actions
// }
// }
try (OutputStream out = new FileOutputStream(f)) {
//some actions
}
return true;
}
});
}
private Object getCacheSyncObject(final Integer id) {
locks.putIfAbsent(id, id);
return locks.get(id);
}
}
public class Main {
public static void main(String[] args) throws IOException {
Object obj = new Object();
Service<Object> service = new Service<>();
Future<Boolean> result1 = service.foo(obj, "filename"); // is there a deadlock?
service.exec.shutdown();
}
}
我想完成一项简单的任务。我需要一个独占文件锁定。为此,我将文件的文件名锁定到同步块。但在这种情况下,我没有从 foo
方法中得到任何东西。我的程序没有结束。
如果你在服务范围内寻找锁,你可以使用它的字段来存储锁。但我建议不要使用 fileName.hashCode() 因为可能会发生冲突。请改用全名:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class Service<T> {
private final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
public final ExecutorService exec = Executors.newFixedThreadPool(5);
public Future<Boolean> foo(T o,
final String fileName) throws IOException {
return exec.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws IOException {
File f = new File(fileName);
synchronized (getCacheSyncObject(fileName)) {
try (OutputStream out = new FileOutputStream(f)) {
out.write("hi".getBytes());
}
}
return true;
}
});
}
private Object getCacheSyncObject(final String name) {
Object result = locks.get(name);
if (result == null) {
result = new Object();
Object prevLock;
if ((prevLock = locks.putIfAbsent(name, result)) != null) {
result = prevLock;
}
}
return result;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Object obj = new Object();
Service<Object> service = new Service<>();
Future<Boolean> result1 = service.foo(obj, "filename");
service.exec.shutdown();
System.out.println("result1 = " + result1.get());
}
}
顺便说一句,即使你与 hashCode() 发生冲突,你也会在文件中得到意想不到的输出,但是如果你没有在那个 try
中锁定任何东西
try (OutputStream out = new FileOutputStream(f)) {
out.write("hi".getBytes());
}
你不应该陷入僵局。我建议检查您的“//某些操作”
我有以下代码片段:
public class Service<T> {
private ConcurrentMap<Integer, Integer> locks = new ConcurrentHashMap<Integer, Integer>();
public final ExecutorService exec = Executors.newFixedThreadPool(5);
public Future<Boolean> foo(T o, String fileName) throws IOException {
return exec.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws IOException {
File f = new File(fileName);
// synchronized (getCacheSyncObject(name.hashCode())) {
// try (OutputStream out = new FileOutputStream(f)) {
// //some actions
// }
// }
try (OutputStream out = new FileOutputStream(f)) {
//some actions
}
return true;
}
});
}
private Object getCacheSyncObject(final Integer id) {
locks.putIfAbsent(id, id);
return locks.get(id);
}
}
public class Main {
public static void main(String[] args) throws IOException {
Object obj = new Object();
Service<Object> service = new Service<>();
Future<Boolean> result1 = service.foo(obj, "filename"); // is there a deadlock?
service.exec.shutdown();
}
}
我想完成一项简单的任务。我需要一个独占文件锁定。为此,我将文件的文件名锁定到同步块。但在这种情况下,我没有从 foo
方法中得到任何东西。我的程序没有结束。
如果你在服务范围内寻找锁,你可以使用它的字段来存储锁。但我建议不要使用 fileName.hashCode() 因为可能会发生冲突。请改用全名:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class Service<T> {
private final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
public final ExecutorService exec = Executors.newFixedThreadPool(5);
public Future<Boolean> foo(T o,
final String fileName) throws IOException {
return exec.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws IOException {
File f = new File(fileName);
synchronized (getCacheSyncObject(fileName)) {
try (OutputStream out = new FileOutputStream(f)) {
out.write("hi".getBytes());
}
}
return true;
}
});
}
private Object getCacheSyncObject(final String name) {
Object result = locks.get(name);
if (result == null) {
result = new Object();
Object prevLock;
if ((prevLock = locks.putIfAbsent(name, result)) != null) {
result = prevLock;
}
}
return result;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Object obj = new Object();
Service<Object> service = new Service<>();
Future<Boolean> result1 = service.foo(obj, "filename");
service.exec.shutdown();
System.out.println("result1 = " + result1.get());
}
}
顺便说一句,即使你与 hashCode() 发生冲突,你也会在文件中得到意想不到的输出,但是如果你没有在那个 try
中锁定任何东西try (OutputStream out = new FileOutputStream(f)) {
out.write("hi".getBytes());
}
你不应该陷入僵局。我建议检查您的“//某些操作”