Week12 - Threads and Network Programming
Week12 - Threads and Network Programming
Becir Isakovic
Lectures Schedule #1
Week 1 - User input, Printing on screen & Conditional statements
Week 3 - Methods, ArrayList data structure, Streams and connecting to the database - Quiz 1
Week 7 - Lambda functions, Records, Optionals , final keyword, & Preparation for the Midterm Exam -
Quiz 3
Lectures Schedule #2
Week 8 & 9 - MIDTERM
Week 10 - Regular expressions, File Manipulation, Iterators, Reflection & Custom Annotations
- In the first example, we will extend the Thread class and override its run method
with the code that we want to be multi-threaded as follows
class CounterMultithreaded extends Thread {
@Override
public void run(){
for(int i = 0; i<=5; i++){
System.out.println(i);
try {
Thread.sleep(1000); // 1 second
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
Threads example cont.
- We also have the .sleep(milliseconds: long) method that pauses the thread for
specified number of milliseconds so we can see the thread execution process
- Now, we want to use this class so it works with multiple threads
- In order to do that we want to create a instance of the class previously created
and call the start() method on it
- That will create a new thread and execute the code that we have wrote in our run
method and go back to the execution of our main method
Threads example cont.
- If the thread calls the yield() method, the scheduler checks if there is any thread
on the ready state waiting to be executed, it moves the current thread to the
Ready state and gives the processor another task.
- yield() method is called on the Thread object and accepts no parameter and does
not return any output.
Threads example cont.
public static void main(String[] args) {
CounterMultithreaded counterMultithreaded = new CounterMultithreaded();
counterMultithreaded.start();
}
- Now, we will see in our console that it is writing the numbers from 0 to 4 where
we have a 1 second delay between each new line written to the console
- Now, let us create one more object instance and see that it is executing the
processes in parallel achieving the multithreading
Threads example cont.
public static void main(String[] args) {
CounterMultithreaded firstCounter = new CounterMultithreaded();
CounterMultithreaded secondCounter = new CounterMultithreaded();
firstCounter.start();
secondCounter.start();
}
- If we, on the other hand, call a run method, the threads will not make any sense
as the second thread will be executed only after the first one finishes processing
the run function, soo we want to use the start method instead as shown in both of
the previous examples
Threads example cont.
- If we want to have 5 threads working in a same time, we just want to iterate and
create them to assure ourselves that it is executing the code at the same time, and
that the each thread runs totally independently of the others
@Override
public void run() {
for (int i = 0; i <= 5; i++) {
System.out.println(i + " from thread " + this.threadNumber);
}
}
}
Threads example cont.
- Now, when we execute the code, we would expect these threads to run the
program in the same order in which they have been created
- But that is not true, the threads are executing every time in a different order
- This tells us that, once we have multiple threads we cannot guarantee the order of
which the threads will be executed
- They are all running in the same time, completely independently one of the other
- One great advantage of using a threads is that, if the exception occurs in one of
these, it will not affect the others
Threads with interface
- As specified at the beginning of the presentation, we can also create the threads
by implementing the interface Runnable
- What is great is that the only thing we would be doing is the same as we have
done by extending the Thread class, we want to provide our own implementation
of the run method, as previously
- However, once we want to run our thread there is a slight difference as we have
to create a new Thread and pass our previously created class that implements
Runnable interface as a constructor parameter and use the start method on the
Thread object as shown in the following code
Threads with interface example
class CounterMultithreaded implements Runnable {
// Rest of the code is unchanged
}
- Let us a develop a program that will read from na URL and get the protocol and
authority that is responsible for the webpage
public static void readUrl(String urlAddress) {
try {
URL url = new URL(urlAddress);
System.out.println("URL is ok, protocol used is " +
url.getProtocol() + ", and the authority " + url.getAuthority());
} catch (MalformedURLException e) {
System.out.println("String " + urlAddress + " is not a valid URL");
}
}
Reading data from webpage
- We are able to communicate with the actual resource on the web by using the
URL class and get the authority and the protocol used
- What if we want to get the content of the webpage
- We will be using the BufferedReader that we have been using previously while
reading from the file, but now the source is the url stream
- After we get all of the information from the website, we are then iterating
through it in order to read it line by line
Reading data from URL example
public static void readPageData(String urlAddress) throws IOException {
URL url = new URL(urlAddress);
BufferedReader inputStream = new BufferedReader(
new InputStreamReader(url.openStream(),
StandardCharsets.UTF_8)
);
String content = "";
String line = null;
while ((line = inputStream.readLine()) != null)
content = content + line;
}
Reading data from URL example cont.
- We have used the https://klix.ba url and we were able to scrap that website by
using the url
- But let us create a more useful application and when we read all data from this
web portal let us use the regex expressions in order to extract the article titles
from the content we have just crawled
- This is extremely widely used approach for scraping the websites
Reading data from URL example with regex
String pattern = "<h2[^>]*>(.*?)</h2>";
while (matcher.find()) {
String h2Content = matcher.group(1);
System.out.println("Matched h2 content: " + h2Content);
}
XML
- The choice between XML and JSON often depends on the specific requirements
and conventions of a given application or system.
<person>
<name>John Doe</name>
<age>30</age>
<city>New York</city>
<isStudent>false</isStudent>
<courses>
<course>Math</course>
<course>History</course>
<course>English</course>
</courses>
</person>
JSON
- JSON is widely used for configuration files, data storage, and communication
between a server and a client in web development. Its simplicity and ease of use
make it a popular choice for these purposes.
{
"name":"John Doe",
"age":30,
"city":"New York",
"isStudent":false,
"courses":[
"Math",
"History",
"English"
]
}
Reading JSON in Java
- In order to use JSON format in the Java application we will add one dependency
to our pom.xml file called json
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
Reading JSON in Java cont.
- Let us create a small method that will read the JSON string to the actual json
object
- We can use the method called getString that will extract the value for a key you
pass as a parameter
- Let us now utilize the previously gained knowledge to read the json from the
URL
- We will use the following online tool to generate the simple JSON and use the
URL to access this resource (https://jsonbin.io/quick-store/)
- In here there is also a two methods that we can use, first getJSONObject(key:
String), to obtain the object and also the getJSONArray(key: String) to obtain the
array from the JSON
Reading JSON in Java from URL cont.
public static void readJson(String urlAddress) throws IOException {
URL url = new URL(urlAddress);
BufferedReader inputStream = new BufferedReader(
new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)
);
String content = "";
String line = null;
while ((line = inputStream.readLine()) != null)
content = content + line;
- These methods provide a way for clients to interact with web servers and perform
various actions on resources.
- The choice of method depends on the nature of the operation the client wants to
perform.
- For example, GET is used for retrieving data, POST for submitting data, PUT for
updating data, and DELETE for removing data.
HttpURLConnection requests in Java
String jsonInput =
"{\"thumbnailUrl\": \"string\", \"title\": \"Hamic\", \"content\": \"Hamigudaa\", \"articleType
\": \"SHORT_ARTICLE\"}";
OutputStream outputStream = connection.getOutputStream();
byte[] input = jsonInput.getBytes("utf-8");
outputStream.write(input, 0, input.length);
System.out.println(connection.getResponseCode());
HttpURLConnection requests in Java explained
- In order to communicate with the server we have to add the headers, that are the
metadata of our actual request specifying the content type of our body and what
we are accepting
- Also the setDoOutput is a method that enables output streams for writing data to
the server.
- Next, we will take our string input and convert it to the byte array that will be
sent to the server as an UTF-8 character encoded string
Sockets
- In Java, the java.net package provides classes and interfaces for working with
sockets. The two main types of sockets in Java are:
- ServerSocket: This class implements a socket that listens for incoming
connections from clients. Once a connection is accepted, a new socket is
created for communication with the client.
- Socket: This class represents a client-side socket that can connect to a
server's socket. It can be used to send and receive data with the server.
Sockets server example
- Let us now implement the Socket server that will accept the remote connections
public static void socketServer(int port) {
try {
ServerSocket serverSocket = new ServerSocket(2345);
while (true) {
Socket connection = serverSocket.accept();
InputStream inputStream = connection.getInputStream();
outputStream.write("Hello, Server!".getBytes());
outputStream.close();
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Sockets client explained
- Now, we want to open a Socket connection to the particular ip address and we
will be using the local ip address of the machine in which we are running the
Socket server
- Next we will use the getBytes() method on the String that we want to send to our
server and use the OutputStream to send the payload to the server that
understands the client message
- NOTE: Do not forget to close your Connection and OutputStream after you finish
your work. YOU ARE ALWAYS ACCOUNTABLE FOR MANAGING THE
RESOURCES THAT YOU ARE USING!
Resources
- https://github.com/ibecir/oop-2023
System.out.println("Thanks, bye!");