У меня проблема с потоком в моем коде, которая не должна происходить - но есть. Поэтому я пытаюсь немного поработать. Я попытаюсь объяснить мои проблемы с простым кодом, как я могу - потому что код, который я испытываю вопрос большой и сложный поэтому в коротком коде:java concurrency - синхронизированный блок
...................
..................
void createAndRunThreads(){
List<Path> pathList = //read path from DB readPath();
for(Path p : pathList){
RunJob rj = new RunJob(p);
Thred t = new Thread(rj);
t.start();
}
}
class RunJob implements Runnable {
private Path path;
private ExecuteJob execJob;
public RunJob(Path path){
this.path = path;
this.execJob = new ExecuteJob();
}
public void run() {
execJob.execute(path);
}
}
class ExecuteJob {
private static Job curentExecutingJob;
public void execute(Path path){
//here every thread should get different job list from others but this is not happening
//so what happens eventually two threads are executing the same Job at once and it gets messy
List<Job> jobList = getJobsFromPath(path);
for(Job job : jobList) {
curentExecutingJob=job;
//work around that I'm trying to do. So if other thread tries to run the same job has to wait on lock(I dont know if this is posible do)
synchronized(curentExecutingJob){
if(job.getStatus.equals("redy")){
//do sum initialization
//and databese changes
job.run();
}
}
}
}
}
Так моя забота, если это будет работа - я не знаю, сравнивается ли объект в блокировке с памятью (должен быть точный объект) или равным (для реализации на нем равным)
Что происходит, когда член static curentExecutingJob имеет один объект-значение в первый поток и создает блокировку на этом (в синхронизованном блоке) и втором изменении потока, которое значение и пытается ввести синхронизированный блок (Мое ожидание, что я надеюсь, это то, что thread-2 продолжит выполнение и onl у времени, что это будет блок, когда он получит ту же работу с БД, что ранее первый поток получил его)
Я не знаю, если этот подход может быть сделан, и имеет смысл
Две нитей выполнив следующий код, который находится внутри метода
1 Job j = getJobByIdFromDB(1111);
2 if(j.status.equals("redye")){
3 do staff
4 make database changes
5 j.run();
6 j.state="running";
7 }
ThreadA является остановка от выполнения в строке 3 из виртуальной машины Java и его состояние меняется от запуска к работоспособной и устанавливается ждать в опросе.
ThreadB дает шанс JVM, а ThreadB выполняет строки 1, 2, 3, 4, 5, 6, что я не хочу. Я хочу, чтобы первый поток, который вводит код в строках 2,3, заканчивается, прежде чем кто-то из остальных потоков имеет шанс ввести тот же код
Проблема заключается в том, что два потока выполняют примерный метод с другим экземпляром, поэтому синхронизированный весь метод не работает - также у меня есть другой код, который был выполнен в этом методе, и я не хочу, чтобы это была синхронизация с
Так есть решение для моей проблемы Также, если я делаю синхронизированный (this.class) {} он потеряет преимущества и смысл многопоточности.
Ну, во-первых, ваша переменная curentExecutingJob объявлена как статическая и будет перезаписана и доступна одновременно. Такой подход на самом деле не так хорош. Что вы ожидаете от этой схемы? – Martin
Считаете ли вы Службой Исполнителя. Это пул потоков с очередью и гарантирует, что каждая задача будет выполняться только одним потоком. –