11. networking and multi-threading
11. networking and multi-threading
Multi-threading
COMP2396 Object-Oriented Programming and Java
Dr. Kenneth Wong
Connecting to Another Program
Owen would like to extend his fantasy adventure game to a
multi-player online game
He adopted the client-server model where each player will
launch a client on his own machine that will be connected to
a server over the network
A client can then communicate with other clients by sending
and receiving messages to and from the server
In Java, sending and receiving data over the network is just
I/O with a slightly different connection stream
All the low-level networking details are taken care of by
classes in the java.net package
1
Client-Server Model
How it works:
Server, I’d like to
1 A client connects to the server connect to the game Waiting for client
requests
Client A
Server
2
Client-Server Model
How it works:
“Magician A casts a
4 Client A sends a message to the healing spell” Message
game server received
Client A
Server
“Magician A casts a
healing spell” Message
5 The server distributes the
distributed to all
message to ALL participants
participants
(including the original sender)
Client A
Server
Client B
3
Connecting, Sending, and Receiving
In order to get his game client working, Owen needs to
learn
1. How to establish the initial connection between the client
and server
2. How to send messages to the server
3. How to receive messages from the server
4. How to send outgoing messages to and simultaneously
receive incoming messages from other participants via
the server
Multi-threading
is the solution!
4
Socket Connection
Client and server applications communicate over a Socket
connection
5
TCP Port
A TCP port is a 16-bit unsigned number assigned to a specific
server application
TCP port numbers allow different clients to connect to the same
machine but communicate with different applications running on
that machine
TCP port numbers from 0 to 1023 are reserved for well known
services (e.g., 80 for HTTP, 23 for Telnet, 20 for FTP, 25 for SMTP,
and 110 for POP3 mail server, etc.)
When writing a server program, you might use any TCP port
number between 1024 to 65535
Only 1 program can be running on a single TCP port. If you try to
bind a program to a port that is already in use, you will get a
java.net.BindException
6
Reading Data from a Socket
The 4 simple steps in reading data from a socket
1. Make a Socket connection to the server
Socket sock = new Socket("127.0.0.1", 5000); 127.0.0.1 is the IP address
for “localhost” (i.e., the one
2. Make an InputStreamReader this code is running on)
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
3. Make a BufferedReader
BufferedReader reader = new BufferedReader(streamReader);
4. Read data
String line = reader.readLine();
destination source
buffered characters converted to characters bytes from server
buffered Data on the
characters 011010011
characters chained to chained to server
Client BufferedReader InputStreamReader Socket’s input stream 7
Server
Writing Data to a Socket
The 3 simple steps in writing data to a socket
1. Make a Socket connection to the server
Socket sock = new Socket("127.0.0.1", 5000);
2. Make a PrintWriter
PrintWriter writer = new PrintWriter(sock.getOutputStream());
source destination
characters bytes to server
Server
"message..." 011010011
chained to program
Client PrintWriter Socket’s output stream 8
Server
Example: Daily Advice Client
Example
import java.io.*;
import java.net.*;
11
Example: Daily Advice Server
Example
import java.io.*;
import java.net.*;
while (true) {
Socket sock = serverSock.accept();
PrintWriter writer = new PrintWriter(sock.getOutputStream());
String advice = getAdvice();
writer.println(advice);
This server application listens for
writer.close();
client requests on port 5000 on the
System.out.println(advice);
machine this code is running on
}
} catch (Exception ex) {
ex.printStackTrace();
}
} // close go
}
The server goes into an infinite loop,
13
waiting for and serving client requests
Multi-threading
The daily advice server code in the previous example has a
serious limitation that it can only handle 1 client at a time
It cannot accept a request from another client until it has
finished with the current client and started the next iteration
of the infinite loop
In order to make the server capable of handling multiple
clients concurrently, separate threads are needed and each
new client Socket should be assigned to a new thread
Similarly, if a client wants to send and receive messages to
and from the server simultaneously, a separate thread
should be created for receiving messages from the server
14
Multi-threading
A thread can be considered as a line of execution. It has its
own call stack for storing method invocations and local
variables
Every application has at least 1 thread running when it is
started (i.e., the main thread)
The main thread can created additional threads (i.e., worker
threads) to handle different tasks in parallel (e.g., reading
from a file, printing to a printer)
Multi-threading refers to the ‘concurrent’ execution of
multiple threads in a single application
Multi-threading often makes an application more responsive
by moving long-running tasks to worker threads
15
Multi-threading in Java
Java has multi-threading built right into the fabric of the
language
A Thread (java.lang.Thread class) is an object that
represents a thread of execution
The 3 simple steps in launching a new thread
1. Make a Runnable object (the thread’s job)
Runnable threadJob = new MyRunnable();
2. Make a Thread object and give it a Runnable (the job)
Thread myThread = new Thread(threadJob);
3. Start the Thread
myThread.start();
16
Runnable Interface
A Runnable object is to a Thread object what a job is to a
worker. It is an instance of a class that implements the
Runnable interface
The Runnable interface defines only 1 method
public interface Runnable {
void run();
}
17
A Multi-threading Example
Example
public class MyRunnable implements Runnable {
public void run() { go(); }
public void go() { doMore(); } What will be the output?
main() run()
RUNNABLE
RUNNING
20
A Multi-threading Example
Scenario 1:
main()starts the The scheduler The scheduler lets The new thread
new thread sends the main the new thread run goes away because
thread out of to completion, its run() completes.
running and back to printing out The main thread
runnable, so that “top of the stack” once again
the new thread can becoming the
run doMore() running thread, and
prints
myThread.start() myThread.start() go() “back in main”
time
Sample output
top of the stack
back in main
21
A Multi-threading Example
Scenario 2:
main()starts the The scheduler The scheduler lets The scheduler The scheduler The new thread
new thread sends the main the new thread run sends the new selects the main returns to the
thread out of for a little while, not thread back to thread to be the running state and
running and back to long enough for the runnable running thread prints out
runnable, so that run() method to again. main()prints “top of the stack”
the new thread can complete out
run “back in main” doMore()
main thread main thread new thread new thread main thread new thread
time
Sample output
back in main
top of the stack
22
Putting a Thread to Sleep
One of the best ways to help your threads take turns is to put them
to sleep periodically
Thread.sleep() can
try { throw an exception
Thread.sleep(2000);
} catch (Exception ex) { ex.printStackTrace(); }
A sleeping thread will not wake up before the specified duration (in
milliseconds)
When a thread wake up, it always goes back to the runnable state
23
Concurrency Problem
Concurrency problem may occur when 2 or more threads
have access to the same object on the heap
Having 2 or more threads accessing the same object at
approximately the same time will result in a race condition,
and may cause data corruption
Example
Mr. and Mrs. Smith share a bank account
They always check the balance before making a withdrawal to
ensure their account will not be overdrawn
The problem is they always fall asleep in between checking the
balance and making the withdrawal
When they wake up, they make the withdrawal without
checking the balance again
24
Mr. & Mrs. Smith Example
Example
public class BankAccount {
private int balance = 100;
public int getBalance() { return balance; }
public void withdraw(int amount) {
balance = balance – amount;
}
}
One single shared
public class SmithJob implements Runnable { bank account
private BankAccount account = new BankAccount();
27
Mr. & Mrs. Smith Example
Sample output
Mr. Smith is about to withdraw
Mr. Smith is going to sleep
Mrs. Smith is about to withdraw
Mrs. Smith is going to sleep
Mr. Smith wakes up
Mrs. Smith wakes up
Mr. Smith completes the withdrawal
Mrs. Smith completes the withdrawal
Overdrawn!
Overdrawn!
Not enough money for Mr. Smith
Not enough money for Mrs. Smith
28
Synchronization
To solve the concurrency problem in the previous example, we
need to make sure that once a thread has checked the account
balance, it has a guarantee that it can wake up and finish the
withdrawal before any other thread can check the account balance
This can be achieved by making the makeWithdrawal() method
atomic
Use the keyword synchronized to modify a method so that only 1
thread at a time can access it
private synchronized void makeWithdrawal(int amount) {
// ...
}
To protect your data (like the bank account), synchronize the
methods that act on that data
29
Using an Object’s Lock
Every Java object has a lock with a single key
Most of time, the lock is unlocked
Object locks come into play only when
there are synchronized methods
A thread can enter one of the synchronized
methods only if it can get hold of the object’s key
Even if an object has more than 1 synchronized method, there is
still only 1 key
Once a thread has entered a synchronized method on an object,
no other threads can enter any synchronized methods on the
same object
30
Deadlock Problem
A thread deadlock happens when you have two
threads, both of which are holding a key the other
thread wants
1 Thread A enters a synchronized 3 Thread B enters a synchronized 5 Thread A wakes up (still holding
method on object foo, and gets method on object bar, and gets the foo key) and tries to enter a
the key. the key. synchronized method on object
bar, but can’t get that key
because B has it. A goes to the
waiting lounge, and waits until
the bar key becomes available.
2 Thread A goes to sleep, holding
the foo key. 4 Thread B tries to enter a
synchronized method on object
foo, but can’t get that key
because A has it. B goes to the
waiting lounge, and waits until 6 Thread A can’t run until it can
the foo key becomes available. get the bar key, but B is holding
B keeps the bar key. the bar key, and B can’t run
until it gets the foo key that A is
holding and …
31
Deadlock Problem
There is no way out of this scenario and the two
threads will simply sit and wait forever!
32