here is my code of main class, because only thread 3 will change the shutdown and main will not read return until thread 3 close so there no need to synchronize it. When I try to run it, the "shutdown" is printed but eclipse say that the program is still running
static Boolean shutdown = false;
public static void main(String[] args) throws InterruptedException, IOException{
System.out.println("Start Server");
final int SocketListSize = 100000;
final int AccListSize = 1000000;
ServerSocket serverSocket;
List<Socket> socketList = Collections.synchronizedList(new ArrayList<Socket>(SocketListSize));
List<Request> requestList = Collections.synchronizedList(new ArrayList<Request>(SocketListSize));
ArrayList<BankAccount> bankAccList = new ArrayList<BankAccount>(AccListSize);
serverSocket = new ServerSocket(1234);
serverSocket.setSoTimeout(50000);
Thread Thread_1 = new Thread(new scanSocketThread(serverSocket, socketList));
Thread Thread_2 = new Thread(new getRequestThread(socketList, requestList));
Thread Thread_3 = new Thread(new ServiceThread(requestList, bankAccList));
Thread_1.start();
System.out.println("thread 1 start");
Thread_2.start();
System.out.println("thread 2 start");
Thread_3.start();
System.out.println("thread 3 start");
Thread_3.join();
System.out.println("thread 3 close");
Thread_1.interrupt();
System.out.println("thread 1 close");
Thread_2.interrupt();
System.out.println("thread 2 close");
if(shutdown == true){
System.out.println("shutdown");
return;
}
Here is what I get
thread 3 close
thread 1 close
thread 2 close
shutdown
If you're looking to kill your program, you can use System.exit(0); instead of the return statement you have now.
More: What are the differences between calling System.exit(0) and Thread.currentThread().interrupt() in the main thread of a Java program?
Related
I want to implement a solution for Readers-Writer problem. The main rule is, only one writer can write at a time and no other writer or reader can write or read, but if a writer doesn't write , multiple readers can read. In the main class, I tried to run threads with executorService.execute but i had some problems i guess. I don't know much about executorService. The program never ends and I guess there is some output problems.
My code is below:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class ReaderWriter {
public static void main(String [] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
ReadWriteLock RW = new ReadWriteLock();
executorService.execute(new Writer(RW));
executorService.execute(new Writer(RW));
executorService.execute(new Writer(RW));
executorService.execute(new Writer(RW));
executorService.execute(new Reader(RW));
executorService.execute(new Reader(RW));
executorService.execute(new Reader(RW));
executorService.execute(new Reader(RW));
}
}
class ReadWriteLock{
static Semaphore readLock = new Semaphore(1);
static Semaphore writeLock = new Semaphore(1);
volatile static int readCount = 0;
public void readLock() throws InterruptedException {
readLock.acquire();
readCount++;
if (readCount == 1) {
writeLock.acquire();
}
readLock.release();
//Reading section
System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
Thread.sleep(1500);
System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
//Releasing section
readLock.acquire();
readCount--;
if(readCount == 0) {
writeLock.release();
}
readLock.release();
}
public void writeLock() throws InterruptedException {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
writeLock.release();
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
}
}
class Writer implements Runnable
{
private ReadWriteLock RW_lock;
public Writer(ReadWriteLock rw) {
RW_lock = rw;
}
public void run() {
while (true){
try {
RW_lock.writeLock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Reader implements Runnable
{
private ReadWriteLock RW_lock;
public Reader(ReadWriteLock rw) {
RW_lock = rw;
}
public void run() {
while (true){
try {
RW_lock.readLock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the output is not right i think for this problem:
Thread pool-1-thread-1 is WRITING
Thread pool-1-thread-2 is WRITING
Thread pool-1-thread-1 has finished WRITING
Thread pool-1-thread-2 has finished WRITING
Thread pool-1-thread-3 is WRITING
Thread pool-1-thread-3 has finished WRITING
Thread pool-1-thread-4 is WRITING
Thread pool-1-thread-4 has finished WRITING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-8 is READING
Thread pool-1-thread-7 is READING
Thread pool-1-thread-6 is READING
Thread pool-1-thread-8 has FINISHED READING
Thread pool-1-thread-5 has FINISHED READING
Thread pool-1-thread-8 is READING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-6 has FINISHED READING
Thread pool-1-thread-6 is READING
Thread pool-1-thread-7 has FINISHED READING
Thread pool-1-thread-7 is READING
Thread pool-1-thread-5 has FINISHED READING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-8 has FINISHED READING
In this output there is 2 writers writing at the same time.
OUTPUT EDIT:
Thread pool-1-thread-1 is WRITING
Thread pool-1-thread-1 has finished WRITING
Thread pool-1-thread-1 is WRITING
Thread pool-1-thread-1 has finished WRITING
Thread pool-1-thread-4 is WRITING
Thread pool-1-thread-4 has finished WRITING
Thread pool-1-thread-3 is WRITING
Thread pool-1-thread-3 has finished WRITING
Thread pool-1-thread-2 is WRITING
Thread pool-1-thread-2 has finished WRITING
Thread pool-1-thread-8 is READING
Thread pool-1-thread-7 is READING
Thread pool-1-thread-5 is READING
Thread pool-1-thread-6 is READING
Thread pool-1-thread-8 has FINISHED READING
Thread pool-1-thread-7 has FINISHED READING
Thread pool-1-thread-5 has FINISHED READING
Thread pool-1-thread-6 has FINISHED READING
The program never ends and i guess there is some output problems.
Add a flag into the ReadWriteLock class to signals the Threads when they should stop working:
private final AtomicBoolean keep_working = new AtomicBoolean(true);
add a method in the ReadWriteLock class to signal the threads to stop:
public void stopThreads(){
keep_working.set(false);
}
and add the method to query the flag:
public boolean keepWorking(){
return keep_working.get();
}
adapt the Writer and Reader run methods, accordingly:
public void run() {
while (RW_lock.keepWorking()){
...
}
}
on the main class add a call to the methods ExecutorService.awaitTermination(), ReadWriteLock.stopThreads, and ExecutorService.shutdown():
public static void main(String [] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
ReadWriteLock RW = new ReadWriteLock();
executorService.execute(new Writer(RW));
executorService.execute(new Writer(RW));
executorService.execute(new Writer(RW));
executorService.execute(new Writer(RW));
executorService.execute(new Reader(RW));
executorService.execute(new Reader(RW));
executorService.execute(new Reader(RW));
executorService.execute(new Reader(RW));
try {
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) { // ...}
RW.stopThreads();
executorService.shutdown();
}
And the output is not right i think for this problem:
(...)
In this output there is 2 writers writing at the same time.
That is because in :
public void writeLock() throws InterruptedException {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
writeLock.release();
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
}
you release the lock before printing "has finished WRITING" therefore, a thread waiting for that lock to be released enters and prints "is WRITING" before the first thread has time to print "has finished WRITING". So you need to change the code to:
public void writeLock() throws InterruptedException {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
writeLock.release();
}
The main rule is, only one writer can write at a time and no other
writer or reader can write or read, but if a writer doesn't write ,
multiple readers can read.
Actually, you can take advantage of the Java ReadWriteLock Interface.
A ReadWriteLock maintains a pair of associated locks, one for
read-only operations and one for writing. The read lock may be held
simultaneously by multiple reader threads, so long as there are no
writers. The write lock is exclusive. All ReadWriteLock
implementations must guarantee that the memory synchronization effects
of writeLock operations (as specified in the Lock interface) also hold
with respect to the associated readLock. That is, a thread
successfully acquiring the read lock will see all updates made upon
previous release of the write lock.
A read-write lock allows for a greater level of concurrency in
accessing shared data than that permitted by a mutual exclusion lock.
It exploits the fact that while only a single thread at a time (a
writer thread) can modify the shared data, in many cases any number of
threads can concurrently read the data (hence reader threads). In
theory, the increase in concurrency permitted by the use of a
read-write lock will lead to performance improvements over the use of
a mutual exclusion lock. In practice this increase in concurrency will
only be fully realized on a multi-processor, and then only if the
access patterns for the shared data are suitable.
By using that interface you could simplify significantly the readLock and writeLock methods, to something as follows:
public void readLock() throws InterruptedException {
shared_resource.readLock().lock();
System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
Thread.sleep(1500);
System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
shared_resource.readLock().unlock();
}
public void writeLock() throws InterruptedException {
shared_resource.writeLock().lock();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
shared_resource.writeLock().unlock();
}
To complete, you should add a variable that counts the number of writes and reads. So that if there is nothing written, the read threads should wait, and in the meantime, the write thread should write something, and so.
You need to invoke the shutdown or shutdownAndAwaitTermination method of the ExecutorService in the main method.
Following is the code (JAVA) that accepts a client socket connection and assigns a thread to each connection.
ServerSocket m_ServerSocket = new ServerSocket();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
Suppose 5 clients are connected, hence 5 threads are running.
client 1: threadId 11
client 2: threadId 12
client 3 :threadId 13
client 4 :threadId 14
client 5 :threadId 15
Suppose one of the clients sends a message "kill-client1" , I to wish end client 1's connection and kill the thread with Id 11, something like this :
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill-client1")) {
// end the connection for client 1 & kill it's corresponding thread 11
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
How can I achieve this ?
Just keep track of all client sockets and/or handling threads.
Map<Integer,Socket> clients=new HashMap<>();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
clients.put(generateNewClientId(),clientSocket);
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
And then if you simply do
{
if (clientCommand.equalsIgnoreCase("Kill")) {
Socket socket=clients.get(idToShutDown);// get required id somehow (from request??)
socket.close();
}
}
This will close given socket resulting in breaking in.readLine() in handling thread thus finishing thread.
If you keep track of threads, you can set "interrupt" flag and probe it in while condition so your handling thread will be able to finish work gracefully.
You could do that by storing your Threads into a thread-safe map (as it will be accessed by several threads concurrently) using the thread id as key
// Map that will contain all my threads
Map<Long, ClientServiceThread> threads = new ConcurrentHashMap<>();
// Add to the constructor the instance of the class that manage the threads
ClientServiceThread cliThread = new ClientServiceThread(this, clientSocket);
// Add my new thread
threads.put(cliThread.getId(), cliThread);
cliThread.start();
Then when a kill is launched
String clientCommand = in.readLine().toLowerCase();
if (clientCommand.startsWith("kill")) {
main.interrupt(Long.valueOf(clientCommand.substring(4).trim()));
}
Then in the main class your method would look like:
public void interrupt(long threadId) {
// Remove the thread from the map
ClientServiceThread cliThread = threads.remove(threadId);
if (cliThread != null) {
// Interrupt the thread
cliThread.interrupt();
}
}
Finally you will need to make your class ClientServiceThread sensitive to interruptions
try {
...
while (!Thread.currentThread().isInterrupted()) {
// My code here
}
} finally {
clientSocket.close();
}
Just terminate the loop:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
running = false;
}
}
or:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
break;
}
}
And don't forget to close the socket in finally block.
To stop the current thread, you close the socket, and return from the run() method:
if (clientCommand.equalsIgnoreCase("Kill")) {
clientSocket.close();
return;
}
EDIT:
To close another thread, you can, for example
share a thread-safe map of clientID-Thread entries between threads. When a new client connects, you store the Thread started for this client in this map
when a Kill-client1 command comes in, you get the Thread corresponging the "client1" key from the map, and call ìnterrupt() on this thread.
in each thread (for example, the client1 thread), at each iteration of the loop, you check what the value of Thread.currentThread().isInterrupted(). If it's true, then you close the connection, remove the thread from the shared map, and return from the run() method.
The key point is that you never kill another thread. You always request a thread to stop by interrupting it, and the thread checks the value of its interrupt flag to decide when and how it must stop.
I have an application that is running jobs that require two threads for every job. The two threads normally do some work and finish shortly after each other. Then after the second thread finishes I need to do some cleanup but since the threads are doing some network IO, it is possible for one thread to get blocked for a long time. In that case, I want the cleanup to take place a few seconds after the first thread finishes.
I implemented this behaviour with the following piece of code in a callback class:
private boolean first = true;
public synchronized void done() throws InterruptedException {
if (first) {
first = false;
wait(3000);
// cleanup here, as soon as possible
}
else {
notify();
}
}
Both threads invoke the done() method when they finish. The first one will then block in the wait() for at most 3 seconds but will be notified immediately when the seconds thread invokes the done() method.
I have tested this implementation and it seems to work well but I'm am curious if there's a better way of doing this. Even though this implementation doesn't look too complicated, I'm afraid that my program will deadlock or have some unsuspected synchronization issue.
I hope I understood your need. You want to wait for thread-a to complete and then wait either 3 seconds or for the end of thread-b.
It is better to use the newer Concurrent tools instead of the old wait/notify as there are so many edge cases to them.
// Two threads running so count down from 2.
CountDownLatch wait = new CountDownLatch(2);
class TestRun implements Runnable {
private final long waitTime;
public TestRun(long waitTime) {
this.waitTime = waitTime;
}
#Override
public void run() {
try {
// Wait a few seconds.
Thread.sleep(waitTime);
// Finished! Count me down.
wait.countDown();
System.out.println(new Date() + ": " + Thread.currentThread().getName() + " - Finished");
} catch (InterruptedException ex) {
System.out.println(Thread.currentThread().getName() + " - Interrupted");
}
}
}
public void test() throws InterruptedException {
// ThreadA
Thread threadA = new Thread(new TestRun(10000), "Thread A");
// ThreadB
Thread threadB = new Thread(new TestRun(30000), "Thread B");
// Fire them up.
threadA.start();
threadB.start();
// Wait for all to finish but threadA must finish.
threadA.join();
// Wait up to 3 seconds for B.
wait.await(3, TimeUnit.SECONDS);
System.out.println(new Date() + ": Done");
threadB.join();
}
happily prints:
Tue Sep 15 16:59:37 BST 2015: Thread A - Finished
Tue Sep 15 16:59:40 BST 2015: Done
Tue Sep 15 16:59:57 BST 2015: Thread B - Finished
Added
With the new clarity - that the end of any thread starts the timer - we can use a third thread for the cleanup. Each thread must call a method when it finishes to trigger the cleanup mechanism.
// Two threads running so count down from 2.
CountDownLatch wait = new CountDownLatch(2);
class TestRun implements Runnable {
private final long waitTime;
public TestRun(long waitTime) {
this.waitTime = waitTime;
}
#Override
public void run() {
try {
// Wait a few seconds.
Thread.sleep(waitTime);
// Finished! Count me down.
wait.countDown();
System.out.println(new Date() + ": " + Thread.currentThread().getName() + " - Finished");
// Record that I've finished.
finished();
} catch (InterruptedException ex) {
System.out.println(Thread.currentThread().getName() + " - Interrupted");
}
}
}
Runnable cleanup = new Runnable() {
#Override
public void run() {
try {
// Wait up to 3 seconds for both threads to clear.
wait.await(3, TimeUnit.SECONDS);
// Do your cleanup stuff here.
// ...
System.out.println(new Date() + ": " + Thread.currentThread().getName() + " - Finished");
} catch (InterruptedException ex) {
System.out.println(Thread.currentThread().getName() + " - Interrupted");
}
}
};
final AtomicBoolean cleanupStarted = new AtomicBoolean(false);
private void finished() {
// Make sure I only start the cleanup once.
if (cleanupStarted.compareAndSet(false, true)) {
new Thread(cleanup, "Cleanup").start();
}
}
public void test() throws InterruptedException {
// ThreadA
Thread threadA = new Thread(new TestRun(10000), "Thread A");
// ThreadB
Thread threadB = new Thread(new TestRun(30000), "Thread B");
// Fire them up.
threadA.start();
threadB.start();
System.out.println(new Date() + ": Done");
}
As done method is synchronized, so only one thread can execute at a time, with this second will wait to send notify until first finishes its whole job, which might cause performance bottleneck.
I would rather design it with short synchronized block which would primarily update the boolean first.
This question already has answers here:
Parallel Computing In Java [closed]
(3 answers)
Closed 8 years ago.
I'm making a twitter analysis software with java and I want to create two threads that run in parallel: One is to stream the tweets using twitter streaming API and one is to analyze. I'm not sure of how to start .
Taken right from a java tutorial. Let me know if you have specific quesitons:
public class SimpleThreads {
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName =
Thread.currentThread().getName();
System.out.format("%s: %s%n",
threadName,
message);
}
private static class MessageLoop
implements Runnable {
public void run() {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
try {
for (int i = 0;
i < importantInfo.length;
i++) {
// Pause for 4 seconds
Thread.sleep(4000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
}
public static void main(String args[])
throws InterruptedException {
// Delay, in milliseconds before
// we interrupt MessageLoop
// thread (default one hour).
long patience = 1000 * 60 * 60;
// If command line argument
// present, gives patience
// in seconds.
if (args.length > 0) {
try {
patience = Long.parseLong(args[0]) * 1000;
} catch (NumberFormatException e) {
System.err.println("Argument must be an integer.");
System.exit(1);
}
}
threadMessage("Starting MessageLoop thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
// loop until MessageLoop
// thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second
// for MessageLoop thread
// to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting!");
t.interrupt();
// Shouldn't be long now
// -- wait indefinitely
t.join();
}
}
threadMessage("Finally!");
}
}
You can start by looking at java.lang.Thread and java.lang.Runnable.
The most basic way to create a thread is to extend Thread or override Runnable.
Simple, a thread is already a seperate process. So two threads are two seperate processes.
ie.
Thread streamThread = new Thread(new Runnable()); // You have to implement the run() method
streamThread.start();
Thread analyzeThread = new Thread(new Runnable()); // You have to implement the run() method
analyzeThread.start();
That's all there is to it.
I am trying to make several consumer threads that listen to one producer thread wait until the producer has something to publish. The code that I thought would work "loses" the lock on being put into and taken out of a shared class.
In a controller class I start the thread running with
Server server = new Server();
Thread serverThread = new Thread(server,"Server");
serverThread.start();
Consumer consumer = new Consumer();
Thread consumerThread;
for (int i =0;i<6;i++){
consumerThread = new Thread(consumer,"Consumer No:"+i);
consumerThread.start();
server.threadRefs[i]= consumerThread;
}
The consumer classes put details of threads into the Map as follows:
public class Consumer implements Runnable {
private ReentrantLock lock = new ReentrantLock();
private Condition cond = lock.newCondition();
#Override
public void run() {
long threadID = Thread.currentThread().getId();
while (true) {
try {
lock.lock();
MDRequest.threadLocks.put(threadID, lock);
System.out.println("Thread " + threadID + " lock = " + lock.toString());
cond.await();
System.out.println("Thread " + threadID + " done waiting");
} catch (InterruptedException ex) {
System.out.println("Interruped " + threadID);
} finally {
lock.unlock();
}
System.out.println("Finished " + threadID);
}
}
The shared class is simply:
public class MDRequest {
protected static ConcurrentHashMap<Long, ReentrantLock> threadLocks = new ConcurrentHashMap<Long, ReentrantLock>();
The Server has the following run() method:
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
Set<Long> keys = MDRequest.threadLocks.keySet();
Long[] threadIDs = keys.toArray(new Long[1]);
// generates a random series of numbers for each thread and notifies threads about them
while (true) {
Random random = new Random();
int threadRef = random.nextInt(5);
System.out.println("About to signal thread " + threadIDs[threadRef].toString());
// notify the thread of the data
ReentrantLock lock = MDRequest.threadLocks.get(threadIDs[threadRef]);
System.out.println("Thread " + threadIDs[threadRef].toString() + " lock = " + lock.toString());
Condition cond = lock.newCondition();
cond.signal();
lock.unlock();
}
The output is as follows:
Thread 11 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Locked by thread Consumer No:0]
Thread 12 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Locked by thread Consumer No:1]
Thread 13 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Locked by thread Consumer No:2]
Thread 14 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Locked by thread Consumer No:3]
Thread 15 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Locked by thread Consumer No:4]
Thread 16 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Locked by thread Consumer No:5]
About to signal thread 14
Thread 14 lock = java.util.concurrent.locks.ReentrantLock#272d7a10[Unlocked]
Exception in thread "Price Server" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1885)
at faster.Server.run(Server.java:46)
at java.lang.Thread.run(Thread.java:695)
From the output int the Server class I can see that when I read the lock out of the Map it now has a status of "Unlocked". When it was put in it had a status of Locked on thread 14.
Why does the reference to the ReentrantLock "lose" the lock?
Is there a way of sharing the lock between the multiple consumer threads and the server thread in a way that the lock is not lost?
The problem you are facing is may be because of the following line in Server
Condition cond = lock.newCondition();
cond.signal();
lock.unlock();
Do you need to call unlock() from the Server for a Lock which is locked by the Consumer? I think calling signal() will suffice.
Think about this.
The problem is thread in Server class tries to unlock but has not lock the Lock
lock.unlock();
Please see ReentrantLock documentation where is clearly stated:
If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown.