Tavo
Tavo

Reputation: 3161

Synchronized method blocks execution

I'm implementing a dummy program with three classes to have a more visual reference of how Futures work. My problem is that sometimes the program will get locked at the synchronized method and it won't go on. And I can't find a reason why. Can someone spot the reason why none of the fighters will print the "I won" line?

My current output when it blocks:

Fighter1

Fighter1 has entered the sync method

Fighter2

Fighter2 has entered the sync method

The code is as follows.

Main class:

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

public class TmpTest {
private static final ExecutorService executorService = 
  Executors.newFixedThreadPool(2);

  public static void main(final String... args) {

    final Fighter fighter1 = new Fighter("Fighter1");
    final Fighter fighter2 = new Fighter("Fighter2");

    final Future<String> submitFighter1 = executorService.submit(fighter1);
    final Future<String> submitFighter2 = executorService.submit(fighter2);

    while (!submitFighter1.isDone() || !submitFighter2.isDone()) {
        if (submitFighter1.isDone()) {
            System.out.println("Fighter 1 wins!");
            submitFighter2.cancel(true);
            executorService.shutdown();
        } else if (submitFighter2.isDone()) {
            submitFighter1.cancel(true);
            System.out.println("Fighter 2 wins!");
            executorService.shutdown();
        }
    }
  }
}

Fighter class:

class Fighter implements Callable<String> {

  private final String fighterName;
  private final ClassWithSyncMethod classWithSyncMethod;

  public Fighter(final String fighterName) {
    this.fighterName = fighterName;
    classWithSyncMethod = new ClassWithSyncMethod(fighterName);
  }

  @Override
  public String call() throws Exception {
    return classWithSyncMethod.syncMethod();
  }
}

Dummy class with synchronized method:

class ClassWithSyncMethod {

  private final String fighterName;

  public ClassWithSyncMethod(final String fighterName) {
    this.fighterName = fighterName;
  }

  public synchronized String syncMethod() {
    System.out.println(fighterName + " has entered the sync method");
    try {
        Thread.sleep(1000);
    } catch (final InterruptedException e) {
        System.out.println("Exception trying to sleep the fighter " + fighterName + ";" + e);
    }
    return fighterName + " shouts: I won!";
  }
}

Upvotes: 1

Views: 50

Answers (1)

Mureinik
Mureinik

Reputation: 311978

This has nothing to do with synchronization. Each fighter synchronizes on a different object, so they don't interfere with each other.

The reason you don't see the "I won" line is much simpler - you never print it. The ClassWithSyncMethod#syncMethod() method (which is returned by Fighter#call()) doesn't print anything, it just returns a value. If you want to print it, you'd have to do so yourself from your main.

E.g.:

while (!submitFighter1.isDone() || !submitFighter2.isDone()) {
    if (submitFighter1.isDone()) {
        System.out.println("Fighter 1 wins!");
        System.out.println(submitFighter1.get()); // Here!
        submitFighter2.cancel(true);
        executorService.shutdown();
    } else if (submitFighter2.isDone()) {
        submitFighter1.cancel(true);
        System.out.println("Fighter 2 wins!");
        System.out.println(submitFighter2.get()); // And here!
        executorService.shutdown();
    }
}

Upvotes: 2

Related Questions