Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
34 views

Advanced Java Programing Individual Assignment

The document discusses threads in Java, which allow for concurrent execution of tasks to improve performance. Threads are lightweight units of execution that can run independently within a process and share system resources. The document also compares threads to processes, and explains multithreading, multitasking, and multiprocessing in Java.

Uploaded by

junedijoasli
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views

Advanced Java Programing Individual Assignment

The document discusses threads in Java, which allow for concurrent execution of tasks to improve performance. Threads are lightweight units of execution that can run independently within a process and share system resources. The document also compares threads to processes, and explains multithreading, multitasking, and multiprocessing in Java.

Uploaded by

junedijoasli
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

DEBRE BERHAN

UNIVERSITY
COLLEGE OF COMPUTING
DEPARTMENT OF COMPUTER
SCIENCE
COURSETITLE:ADVANCED JAVA PROGRAMMING

COURSECODE:COSC3053

INDIVIDUAL ASSIGNMENT
NAME: MELKAMU AWTACHEW
ID:3869/13
What is Thread?
Threads: is a lightweight unit of execution within a program. It is a fundamental part of Java's
multithreading support, allowing concurrent execution of multiple tasks or processes within a
single program. It’s refers to a sequence of instructions that can be executed independently
within a program. It also refers to a separate flow of execution within a program that can run
independently of other threads. Threads allow different parts of a program to execute
concurrently, leading to improved performance, responsiveness, and utilization of system
resources.
Thread can be thought of as an independent path of execution that operates within a larger
program. It enables the program to perform multiple tasks simultaneously, leading to increased
efficiency and responsiveness. They provide a way to achieve multitasking and increase the
efficiency of program execution by dividing tasks into smaller units that can be executed
concurrently. Multiple threads can exist within a single process, allowing for concurrent
execution of tasks.
Java threads are managed by the Java Virtual Machine (JVM) and provide features such as
synchronization, which allows threads to communicate and coordinate with each other.
Threads can be created by extending the Thread class or implementing the Runnable interface
in Java. Each Java program has at least one thread, known as the main thread, which is
automatically created when the program starts. Additional threads can be created by the
programmer to perform specific tasks concurrently. These threads can run concurrently,
meaning they can execute simultaneously, or they can be scheduled to run at different times
based on the program's requirements.
In summary, threads in Java are used to achieve concurrent execution of tasks, allowing
programs to utilize system resources efficiently and provide better responsiveness. By dividing a
program's workload into multiple threads, developers can take advantage of parallelism and
create more efficient and responsive applications.
Multithreading, Multitasking, Multiprocessing
A. Multithreading: is a process of executing two or more threads simultaneously for
maximum utilization of the CPU. It’s also the capability of a program to execute multiple
threads concurrently. It is a technique that allows different parts of a program to run
simultaneously, enabling concurrent execution of tasks and taking advantage of
available system resources. It’s saves time as you can perform multiple operations
together and the threads are independent, so it does not block the user to perform
multiple operations at the same time and also, if an exception occurs in a single thread,
it does not affect other threads. Multithreading enables concurrent execution of tasks
by dividing them into separate threads. It provides the means to create, manage, and
coordinate threads, allowing for parallel execution, improved performance, and
responsiveness in Java applications.
Some examples of Multithreading are Web browser, Word processor Video processor.

B. Multitasking: is the ability of a program to execute multiple tasks concurrently. It can


be achieved using threads, which are lightweight units of execution within a program.
Multitasking enables users to run multiple applications at the same time and allows for
efficient sharing of system resources among different processes. The ability to perform
multitasking in Java allows for efficient utilization of system resources and enables
concurrent execution of multiple tasks, leading to improved performance and
responsiveness in applications.
Multitasking can be achieved by creating and starting multiple threads, each performing a
specific task or operation. By using multitasking, Java programs can perform tasks concurrently,
which can lead to improved performance, responsiveness, and utilization of system resources.
Threads can execute independently, allowing for parallelism when running on multi-core
processors.
There are two basic types of multitasking in Java:
1. Process-based Multitasking (Multiprocessing): Process-based multitasking is known
as multiprocessing. In multiprocessing, each process has an address in the memory. In
other words, each process allocates a separate memory area. A process is a
heavyweight. The cost of communication between the processes is high. Saving and
loading of registers, memory maps, and updating lists are required to switch from one
process to another. Java supports multitasking at the process level, where multiple
processes can run concurrently on a computer system. Each process has its own
memory space and resources, and they are managed by the operating system.
2. Thread-based Multitasking (Multithreading): Thread-based multitasking is known
as multithreading in java. At least one process is required for each thread. A thread is
lightweight. The cost of communication between the threads is low. In this article, we
are going to know the details about multithreading in java. Java's primary mechanism
for multitasking is through threads. A thread is a lightweight unit of execution within a
program. It allows different parts of a program to run concurrently within the same
process. Threads share the same memory space and resources, but each thread has its
own execution context.
C. Multiprocessing: is the execution of multiple processes concurrently, where each
process runs independently and can perform different tasks simultaneously. Java
provides support for multiprocessing through the use of threads. They require multiple
physical processors for executing a complex process. Multiple threads can be created
within a Java program, and each thread can perform a separate task independently.
Threads within a process share the same memory space, allowing for efficient
communication and data sharing between them.
It's is the utilization of two or more central processing units (CPUs) in a single computer system.
Its definition can vary depending on the context, but generally it refers to a system's ability to
support multiple CPUs and its capacity to distribute work among them.

Process vs Thread
Process: is an active program that is under execution. It is more than the program code, as it
includes the program counter, process stack, registers, program code etc. Compared to this, the
program code is only the text section. It represents the execution of a Java application, which
can consist of multiple threads. Each Java process has its own memory space, system resources,
and a separate instance of the Java Virtual Machine (JVM) running the application. When you
run a Java program, it starts a new process that operates independently of other processes.
Each process runs independently and is isolated from other processes, meaning that it has its
own memory space and cannot directly access or modify the memory of other processes.
Processes are managed by the operating system, which schedules their execution, assigns
system resources, and facilitates inter-process communication. Processes communicate with
each other through inter-process communication (IPC) mechanisms, such as pipes, shared
memory, or message passing.
Thread: is a unit of execution within a Java process. It is a lightweight sequence of instructions
that can run concurrently with other threads within the same process. Java threads are
instances of the java.lang. Thread class or can be created by implementing the java.lang.
Runnable interface. Multiple threads within a Java process share the same memory space,
allowing for efficient communication and data sharing between them. Java's multithreading
capabilities allow you to create and manage multiple threads within a single Java process. This
enables concurrent execution of tasks, improves performance, and enhances responsiveness in
applications. By leveraging threads, you can achieve parallelism and efficiently utilize available
system resources.
A thread shares information like data segment, code segment, files etc. with its peer threads
while it contains its own registers, stack, counter etc. It’s basically a subpart of a large process.
In a process, all the threads within it are interrelated to each other. A typical thread contains
some information like data segment, code segment, etc. This information is being shared to
their peer threads during execution. The most important feature of threads is that they share
memory, data, resources, etc. with their peer threads within a process to which they belong.
 Both processes and threads are related to each other and very much similar, hence
create confusion to understand the differences between both of them. The process and
thread are an independent sequence of execution, but both are differentiated in a way
that processes execute in different memory spaces, whereas threads of the same
process execute in shared memory space.
o The main difference between process and thread are that a process represents the
execution of a Java program and is isolated from other processes, while a thread is a
unit of execution within a Java process and allows for concurrent execution of tasks
within the same memory space. Processes have their own memory and resources,
whereas threads share resources within a process. Threads are lightweight and used for
achieving concurrency within a Java program, while processes are independent
instances of Java programs.

Thread-based multitasking and multithreading


A. Thread-based multitasking (concurrent programming): is executing multiple tasks
or activities simultaneously within a program using threads. There can be two or more
threads can be run concurrently. In Java, this can be achieved by creating multiple
threads that perform different tasks concurrently. Each thread represents an
independent flow of control within the program, allowing for parallel execution of
multiple activities. By utilizing thread-based multitasking, you can improve the efficiency
and responsiveness of your Java program, particularly in scenarios where tasks can be
executed independently or tasks involve waiting for I/O operations. For example, you
can create one thread to handle user input, another thread to perform time-consuming
calculations, and yet another thread to update the user interface concurrently. This way,
different parts of the program can execute simultaneously, enhancing overall
performance.
The process of multi-tasking let’s a CPU execute various tasks at the very same time. The
process of multi-threading lets a CPU generate multiple threads out of a task and process all of
them simultaneously. A user can easily perform various tasks simultaneously with their CPU
using multi-tasking. In thread-based multitasking, the thread is the smallest unit of dispatchable
code. This means that a single program can perform two or more tasks simultaneously.
Example: A Text Editor can format text at the same time it is printing, as long as these two
actions are performed by two separate threads.

B. Multithreading: is the practice of utilizing multiple threads within a program to achieve


concurrent execution. In Java, multithreading is accomplished by creating instances of
the java.lang.Thread class or implementing the java.lang.Runnable interface. Each
thread represents a separate flow of control within the program, allowing different
parts of the code to execute simultaneously.

Java's multithreading capabilities enable you to create, manage, and coordinate multiple
threads within a single program. Threads within a Java program share the same memory space,
enabling efficient communication and data sharing. However, it's crucial to handle thread
synchronization and potential race conditions when multiple threads access shared data to
ensure data integrity and avoid conflicts.
By utilizing multithreading in Java, you can effectively utilize system resources, improve
responsiveness, and achieve parallelism within your program, leading to enhanced
performance and better user experience. It is commonly used in scenarios such as graphical
user interfaces (GUIs), server applications, and computationally intensive tasks. For example, in
a GUI application, you can use separate threads to handle user input, update the interface, and
perform background computations simultaneously, ensuring smooth user interaction. It
enables you to enhance the performance and responsiveness of your program by leveraging
the capabilities of modern processors with multiple cores or support for simultaneous
multithreading (SMT). By dividing the workload into multiple threads, you can achieve parallel
execution of tasks, making efficient use of available system resources.

Multi-thread and Thread synchronization, and priorities


A. Multi-thread: refers to the practice of utilizing multiple threads within a java program
to achieve concurrent execution. It involves creating and managing multiple threads
that can execute different parts of the program's code simultaneously. In multi-
threaded programs, different threads execute independently and can perform separate
tasks at same time, allowing for parallelism and efficient utilization of system resources.
Each thread represents a separate flow of control within the program, enabling
concurrent execution of different parts of the code. Multi-thread is commonly used to
improve performance, responsiveness, and scalability in applications.

Multithreading allows many parts of a program to run simultaneously. These parts are referred
to as threads, and they are lightweight processes that are available within the process. As a
result, multithreading increases CPU utilization through multitasking. By utilizing multi-
threading, Java programs can achieve parallelism and make efficient use of available system
resources, such as CPU cores. Java provides built-in support for multi-threading through the
java.lang. Thread class and the java.lang.Runnable interface.

Multithreading enables us to run multiple threads concurrently. For instance, in a web browser,
we can have one thread which handles the user interface, and in parallel we can have another
thread which fetches the data to be displayed. Therefore, multithreading improves the
responsiveness of a system.
B. Thread Synchronization: is the process of coordinating the execution of multiple
threads to ensure orderly and predictable behavior. It’s a way of programming several
threads to carry out independent tasks easily. It is capable of controlling access to
multiple threads to a particular shared resource. The main reason for using thread
synchronization is to prevent interference between threads. In multi-threaded
programs, threads may need to access shared resources or critical sections of code
concurrently. Synchronization mechanisms, such as locks, semaphores, or monitors, are
used to control access to these shared resources and prevent data corruption or race
conditions. Java provides keywords like synchronized and classes like Lock and
Semaphore for thread synchronization.

Java provides synchronization mechanisms that allow threads to safely access shared resources.
The most commonly used synchronization mechanism in Java is the synchronized keyword,
which can be applied to methods or code blocks. When a thread encounters a synchronized
block or method, it acquires a lock on the associated monitor, ensuring that only one thread
can execute the synchronized code at a time. Other threads attempting to access the same
synchronized block or method will be blocked until the lock is released. By properly
synchronizing access to shared resources, thread synchronization prevents data corruption and
ensures data integrity. It establishes a happens-before relationship, ensuring that changes
made by one thread are visible to other threads.

It is essential when multiple threads access shared resources concurrently. It helps maintain
data consistency, prevents race conditions, and ensures the correct execution of multi-
threaded programs. However, it's important to use synchronization judiciously to avoid
potential performance bottlenecks or deadlocks. Understanding and applying proper
synchronization techniques are critical for developing robust and thread-safe Java applications.
Additionally, thread synchronization can be used for signaling and communication between
threads, allowing them to coordinate their activities and avoid unnecessary waiting or busy-
waiting.

C. Priorities: represent the relative importance of threads for CPU scheduling. Each thread
in Java is assigned a priority value that ranges from 1 to 10. The larger the integer, the
higher the priority. But it is not guaranteed because it depends on JVM specification that
which scheduling it chooses. Note that not only JVM a Java programmer can also assign
the priorities of a thread explicitly in a Java program. The thread scheduler uses this
integer from each thread to determine which one should be allowed to execute. The
default priority of a thread is usually inherited from its parent thread.

Thread priorities are used to provide guidance to the Java thread scheduler, which sets the
order in which threads receive CPU time. They are typically used to indicate the relative
importance or urgency of different threads within an application. Threads with higher priorities
are more likely to be scheduled and executed by the scheduler than threads with lower
priorities. It is crucial to remember, however, that thread priorities are not strictly guaranteed
and may vary among platforms and JVM implementations.

The setPriority() function of the Thread class in Java can be used to set the priority of a thread.
The getPriority() method can also be used to retrieve a thread's priority.It is important to use
thread priorities wisely and understand their limitations. While higher priority threads are more
likely to be scheduled, strict ordering and fairness are not guaranteed. It is generally not
advisable to rely only on thread priority for crucial synchronization or timing requirements.

Types of synchronization
Synchronization: is the ability to regulate multiple processes’ access to a shared resource. It’s
a mechanism used to coordinate and control access to shared resources or critical sections of
code in a multi-threaded environment. Multiple threads attempt to access shared resources at
the same time under the Multithreading concept, resulting in inconsistent outcomes.
Synchronization is required for thread-to-thread communication to be reliable. Synchronization
aids in thread interference prevention. It helps on the prevention of concurrency issues.
Synchronization is crucial for maintaining thread safety and preventing race conditions and data
corruption in multi-threaded applications. By properly synchronizing access to shared
resources, developers can ensure correct and predictable behavior of their concurrent
programs. It ensures that only one thread can access a shared resource or execute a critical
section at a time, preventing conflicts and maintaining data consistency.

 There are two forms of synchronization:

A. Process synchronization: is the coordination between independent processes running


in parallel. It is necessary when multiple processes need to access shared resources or
communicate with each other. Process synchronization mechanisms include techniques
such as semaphores, locks, and message passing. These mechanisms help prevent race
conditions, deadlocks, and other synchronization-related issues.

It operates in a separate process that is not connected to another. The operating system
allocates resources to the process, such as memory and CPU time. The phrase “process
synchronization” refers to the sharing of capabilities between two or more processes while
guaranteeing data consistency. The Critical Section is a piece of code that is shared by several
processes in a programming language. There are various methods to prevent critical section
problems, such as Peterson’s Solution, but the most famous is Semaphores.

B. Thread synchronization: is form of synchronization that focus on coordinating the


activities of multiple threads within a single process. Threads are lightweight units of
execution that share the same memory space. Thread synchronization is crucial when
multiple threads access shared data concurrently. Common thread synchronization
techniques in Java include synchronized blocks, locks (such as ReentrantLock), and
concurrency utilities like CountDownLatch and CyclicBarrier.

It refers to the concurrent execution of a vital resource by two or more Threads. A


thread is a subroutine that can run separately within the context of a single process. A
single process can have numerous threads, and the program can schedule all of the
threads to use a vital resource. A single thread, in reality, includes numerous threads.

Types of thread synchronization


 There are two types of thread synchronization:

1. Mutual Exclusive: also known as a Mutual Exclusive, allows only one thread to access
shared resources. In other word it is the property where only one thread can access a
shared resource or a critical section of code at a time. This prevents conflicts and data
inconsistencies. In Java, mutual exclusion can be achieved using the synchronized
keyword or Lock objects. It will not enable simultaneous access to shared resources.
 Here is one example for mutual exclusive thread synchronization:

In this example, we have a “PrintJob” class with a “print” method that is declared as
synchronized. This ensures that only one thread can execute the “print” method at a time.

We create two “PrinterThread” objects, passing the same “PrintJob” instance and different
document names to each thread. When the threads start, they invoke the “print” method on
the shared “PrintJob” object. Due to the synchronized keyword, only one thread can access the
“print” method at a time, ensuring mutual exclusion. As a result, the documents are printed
sequentially, preventing conflicts and maintaining data consistency. The threads are separate
instances, but they synchronize their access to the shared “PrintJob” object, achieving mutual
exclusion.

Implementation:

class PrintJob {

public synchronized void print(String document) {

for (int i = 0; i < 5; i++) {

System.out.println("Printing: " + document);

class PrinterThread extends Thread {

private PrintJob printJob;

private String document;


public PrinterThread(PrintJob printJob, String document) {

this.printJob = printJob;

this.document = document;

@Override

public void run() {

printJob.print(document);

public class Main {

public static void main(String[] args) {

PrintJob printJob = new PrintJob();

PrinterThread thread1 = new PrinterThread(printJob, "Document 1");

PrinterThread thread2 = new PrinterThread(printJob, "Document 2");

thread1.start();

thread2.start();

}
 Types of Mutual exclusion threads:
A. Synchronized Method: It provides the synchronized keyword, which can be applied
to methods to achieve mutual exclusion. When a thread enters a synchronized method,
it acquires the lock associated with the object instance or class. Other threads
attempting to execute synchronized methods on the same object or class must wait
until the lock is released. When a method is declared as synchronized, only one thread
can execute that method at a time, ensuring mutual exclusion.

Example:
public class SynchronizedMethodExample {

private int count = 0;

public synchronized void increment() {

count++;

B. Synchronized block: Java allows the use of synchronized blocks to create smaller
critical sections within methods. With synchronized blocks, a thread acquires the lock
associated with the specified object or class before entering the block. A synchronized
block allows you to create a smaller critical section within a method. Only one thread
can enter the synchronized block at a time, ensuring mutual exclusion within that
block.
Example:
public class SynchronizedBlock() {
private int count = 0;
private Object lock = new Object();

public void increment() {


// Non-critical section

synchronized (lock) {
// Critical section
count++;
}

// Non-critical section
}
}

C. Static Synchronization: When a static method is declared as synchronized, only one


thread can execute that method at a time for all instances of the class, ensuring mutual
exclusion across all objects.

Example:
public class StaticSynchronizationExample {

private static int count = 0;

public static synchronized void increment() {

count++;

2. Inter Thread Communication: is a mechanism in which a thread is paused running in


its critical section and another thread is allowed to enter (or lock) in the same critical
section to be executed. It is done with the help of three final methods defined in the
Object class: wait(), notify(), and notifyAll(). The wait() method puts the current thread
into a sleep state and releases the monitor until some other thread holds the monitor
and invokes the notify() or notifyAll() method. Mailbox service is a typical inter-thread
communication method in real-time operating systems. For example, there are two
threads, thread 1 detects the state of the button and sends it's state, and thread 2 reads
the state of the button and turns on or off the LED according to the state of the button.
 Here is one example for Inter-Thread Communication:

In this example, the “setMessage” method sets the message content and notifies other threads
waiting on the object. The “getMessage” method retrieves the message and notifies waiting
threads. The “wait()” method suspends the calling thread until it is notified by another thread
using “notify()” or “notifyAll()”. It demonstrate how mutual exclusion and inter-thread
communication can be implemented in Java. By ensuring mutual exclusion, we prevent
concurrent access to shared resources, while inter-thread communication allows threads to
synchronize their actions and share information effectively.

Implementation:

class Message {

private String content;

private boolean isMessageReady = false;

public synchronized void setMessage(String message) {

while (isMessageReady) {

try {
wait();

} catch (InterruptedException e) {

e.printStackTrace();

content = message;

isMessageReady = true;

notifyAll();

public synchronized String getMessage() {

while (!isMessageReady) {

try {

wait();

} catch (InterruptedException e) {

e.printStackTrace();

isMessageReady = false;

notifyAll();

return content;

}
 The Object class in java contains three final methods that allows threads to
communicate about the lock status of a resource. These methods are wait(), notify()
and notifyAll().

 Wait(): . It is called inside a synchronized context (synchronized block or synchronized


method) to release the lock and allow other threads to execute. Object wait methods
has three variance, one which waits indefinitely for any other thread to call “notify” or
“notifyAll” method on the object to wake up the current thread. Other two variances
place the current thread in wait for specific amount of time before they wake up
Example:

package com.journaldev.concurrency

public class Waiter implements Runnable{

private Message msg;

public Waiter(Message m){

this.msg=m;

@Override

public void run() {

String name = Thread.currentThread().getName();

synchronized (msg) {

try{

System.out.println(name+" waiting to get notified at


time:"+System.currentTimeMillis());

msg.wait();
}catch(InterruptedException e){

e.printStackTrace();

System.out.println(name+" waiter thread got notified at


time:"+System.currentTimeMillis());

//process the message now

System.out.println(name+" processed: "+msg.getMsg());

 notify(): It is called inside a synchronized context to notify a waiting thread that it can
proceed. notify method wakes up only one thread waiting on the object and that thread
starts execution. So if there are multiple threads waiting for an object, this method will
wake up only one of them. The choice of the thread to wake depends on the OS
implementation of thread management. After notify() is called, the awakened thread
does not immediately regain the lock. It must wait for the notifying thread to release the
lock before it can proceed.

Example:
package com.journaldev.concurrency;
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+" started");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name+" Notifier work done");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

 notifyAll(): It is called inside a synchronized context to notify all waiting threads that
they can proceed. notifyAll method wakes up all the threads waiting on the object,
although which one will process first depends on the OS implementation. These
methods can be used to implement producer consumer problem where consumer
threads are waiting for the objects in Queue and producer threads put object in queue
and notify the waiting threads. Let’s see an example where multiple threads work on
the same object and we use wait, notify and notifyAll methods. After notifyAll() is called,
the awakened threads do not immediately regain the lock. They must wait for the
notifying thread to release the lock before they can proceed.
Example:
package com.journaldev.concurrency;
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter = new Waiter(msg);
new Thread(waiter,"waiter").start();
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
}
In this example, the Message class represents a shared message object between the Producer
and Consumer threads. The produce() method is used by the producer to set the content of the
message, and the consume() method is used by the consumer to retrieve the content of the
message. The methods are synchronized and use the wait() and notify() calls to control the
execution flow. The producer waits when the message is not empty, and the consumer waits
when the message is empty. The notify() calls notify the waiting threads to resume execution.

You might also like