2015-08-22 6 views
0

Что не так с кодом, мои потоки не синхронизируются: У меня в приведенном ниже примере синхронизированный метод печати, который будет вызывать поток, но все же вывод показывает, что потоки не синхронизируются при доступе к методу печати. См. Вывод ниже.что случилось с синхронизированным

Главный класс

public class ExecutorTester { 

    public static void main(String[] args) { 

     PrinterRunnable pr = new PrinterRunnable(); 
     ExecutorService excutor = Executors.newFixedThreadPool(20); 
     //ExecutorService excutor = Executors.newSingleThreadExecutor(); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 

     excutor.shutdown(); 

     for(int i =0; i<5;i++) 
      System.out.println("In Main Thread : "+i); 
    } 
} 

Класс Thread

public class PrinterRunnable implements Runnable { 

    @Override 
    public void run() { 
     for(int i =0; i<5;i++){ 
      //System.out.println("In Thread class" +i); 
      Printer p = new Printer(); 
      p.print(i); 
     } 
    } 
} 

другой класс

public class Printer { 

    public synchronized void print(int i){ 
     System.out.println("Entered Thread: "+Thread.currentThread().getId()); 
     System.out.println("In thread: "+Thread.currentThread().getId()+"count::"+i); 
     System.out.println("Exit Thread: "+Thread.currentThread().getId()); 
    } 
} 

Console Output (см ниже резьбы 13 и 11 оба вошли !!!)

Entered Thread: 13 
Entered Thread: 11 
In thread: 11count::0 
Exit Thread: 11 
Entered Thread: 11 
In thread: 11count::1 
Exit Thread: 11 
In thread: 13count::0 
Exit Thread: 13 
Entered Thread: 13 
In thread: 13count::1 
Exit Thread: 13 
........ 
........ 
........ 
+0

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

ответ

0

Метод synchronized это за экземпляр объекта, и, как вы создаете несколько экземпляров нет разногласий. В зависимости от ваших требований вы можете изменить метод на static или синхронизировать с переменной класса.

+0

Большое спасибо за быструю помощь – Alex

0

Они синхронизированы, конечно. Каждый на своем собственном мониторе связан с собственным объектом принтера. Поскольку вы создаете 5 различных объектов принтера, «синхронизированных», выполняемых на разных объектах, и никогда не блокируйте процесс выполнения.

Вы должны создать один объект и использовать его для синхронизации. , например:

public class Printer { 

    public void print(int i){ 
     syncrhonized(Printer.class) { 
      System.out.println("Entered Thread: "+Thread.currentThread().getId()); 
      System.out.println("In thread: "+Thread.currentThread().getId()+"count::"+i); 
      System.out.println("Exit Thread: "+Thread.currentThread().getId()); 
     } 
    } 
} 

, поскольку существует только один объект Printer.class, они всегда будут synchroinzed.

+0

Большое спасибо за быструю помощь – Alex

3

Когда ключевое слово synchronized является частью сигнатуры метода, как это происходит в

public synchronized void print(int i) 

, то эта синхронизация относится к например, что этот метод вызывается. Каждый раз, когда вы хотите что-то печатать, вы создаете один новый экземпляр Printer.

Для достижения желаемого эффекта вам необходимо синхронизировать один общий объект. Это может, например, быть достигнуто, как это:

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class ExecutorTester 
{ 
    public static void main(String[] args) 
    { 
     PrinterRunnable pr = new PrinterRunnable(new Object()); 
     ExecutorService excutor = Executors.newFixedThreadPool(20); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 
     excutor.submit(pr); 

     excutor.shutdown(); 

     for (int i = 0; i < 5; i++) 
      System.out.println("In Main Thread : " + i); 
    } 
} 

class PrinterRunnable implements Runnable 
{ 
    private final Object monitor; 

    PrinterRunnable(Object monitor) 
    { 
     this.monitor = monitor; 
    } 

    @Override 
    public void run() 
    { 
     for (int i = 0; i < 5; i++) 
     { 
      // System.out.println("In Thread class" +i); 
      Printer p = new Printer(monitor); 
      p.print(i); 
     } 
    } 
} 

class Printer 
{ 
    private final Object monitor; 

    Printer(Object monitor) 
    { 
     this.monitor = monitor; 
    } 

    public void print(int i) 
    { 
     synchronized (monitor) 
     { 
      System.out.println("Entered Thread: " + 
       Thread.currentThread().getId()); 
      System.out.println("In thread: " + 
       Thread.currentThread().getId() + " count::" + i); 
      System.out.println("Exit Thread: " + 
       Thread.currentThread().getId()); 
     } 
    } 
} 

Но, конечно, это слишком прагматичны эскиз. В вашем реальном приложении вы должны тщательно подумать о , который объект, который вы хотите синхронизировать.

+0

Большое спасибо за помощь – Alex

1

В этом месте:

@Override 
public void run() { 
    for(int i =0; i<5;i++){ 
     //System.out.println("In Thread class" +i); 
     Printer p = new Printer(); 
     p.print(i); 
    } 
} 

каждый поток создает свой собственный принтер для каждой итерации. Синхронизация работает, останавливая другие потоки от выполнения синхронизированных методов на одном и том же объекте до тех пор, пока один поток не завершится с его синхронизированным методом.В соответствии с: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

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