2013-08-06 6 views
2

У меня проблема с потоком в моем коде, которая не должна происходить - но есть. Поэтому я пытаюсь немного поработать. Я попытаюсь объяснить мои проблемы с простым кодом, как я могу - потому что код, который я испытываю вопрос большой и сложный поэтому в коротком коде: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) {} он потеряет преимущества и смысл многопоточности.

+0

Ну, во-первых, ваша переменная curentExecutingJob объявлена ​​как статическая и будет перезаписана и доступна одновременно. Такой подход на самом деле не так хорош. Что вы ожидаете от этой схемы? – Martin

+0

Считаете ли вы Службой Исполнителя. Это пул потоков с очередью и гарантирует, что каждая задача будет выполняться только одним потоком. –

ответ

0

Не могу прокомментировать, поэтому я поставлю его как ответ. Сожалею.

Блок

синхронизирована (curentExecutingJob)

синхронизируется на объект curentExecutingJob (в ваших терминах, память). Если вы синхронизируете другой объект otherExecutingJob с currentExecutingJob.equals (otherExecutingJob) == true, оба оператора синхронизации не будут влиять друг на друга.

На ваш вопрос/проблему: Было бы полезно описать, что делает или должно делать getJobsFromPath и то, что вы на самом деле хотите сделать, и какова ваша проблема на самом деле. Мне это не совсем понятно.

+0

Я предполагаю, что он хочет синхронизировать потоки, которые фактически меняют один и тот же объект и создают там определенные проблемы, он хочет синхронизировать все потоки, когда они пытаются отредактировать один и тот же объект, чтобы синхронизировать их между собой в некотором порядке ... –

0

я видел ваш код, который он проверяет для статуса работы, если он готов или нет, ну как я думаю, что это не afeasible способ

вы можете использовать отзывной интерфейс вместо Runnable

вот пример, который может вам помочь.

Java Concurrency

1

Проблема заключается в том, что «currentExecutingJob» определяется как статические, а это означает, что все экземпляры ExecuteJob одни и те же «» экземпляр этой переменной. Кроме того, вы устанавливаете значение этой переменной за пределы блока синхронизации, а это означает, что каждый поток будет устанавливать его неконтролируемым образом. Ваш следующий блок синхронизации не должен иметь никакого практического влияния.

Учитывая, что ваш образец кода написан, мне кажется, что вам не нужны какие-либо статические переменные, и вам не нужна синхронизация, так как нет ресурсов, разделяемых несколькими потоками.

Однако ваши комментарии в коде указывают, что вы хотите, чтобы два потока выполняли одно и то же задание одновременно. Ваш код не достигает этого, так как нет сопоставления выполняемых заданий, чтобы увидеть, работает ли одно и то же задание, и даже если было сравнение, вашему getJobsFromPath() нужно было бы создать список заданий, чтобы тот же экземпляр объекта необходимо будет повторно использовать, когда два потока/пути сталкиваются с одним и тем же «заданием».

Я не вижу в этом коде ничего подобного.

Смежные вопросы