0% found this document useful (0 votes)
2 views18 pages

Java program 1

The document discusses synchronization in Java to prevent UI corruption, emphasizing the importance of using the Event Dispatch Thread (EDT) for UI updates. It provides examples of synchronization mechanisms such as SwingUtilities.invokeLater(), synchronized blocks, and volatile variables, alongside code snippets demonstrating their implementation. Additionally, it covers thread priorities, a generic Matrix class, and a Buffer class for producer-consumer scenarios, highlighting the use of wait() and notifyAll() for inter-thread communication.

Uploaded by

evungu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views18 pages

Java program 1

The document discusses synchronization in Java to prevent UI corruption, emphasizing the importance of using the Event Dispatch Thread (EDT) for UI updates. It provides examples of synchronization mechanisms such as SwingUtilities.invokeLater(), synchronized blocks, and volatile variables, alongside code snippets demonstrating their implementation. Additionally, it covers thread priorities, a generic Matrix class, and a Buffer class for producer-consumer scenarios, highlighting the use of wait() and notifyAll() for inter-thread communication.

Uploaded by

evungu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

/* Group number 7

1. Mary Joseph Tresford 23100934340096


2. Asha Omar Selemani 23100934340094
3. Naomi Mlowe 23100934340098
4. Igembe Lucas 23100934340041
5. Martin Paschal Gibole 23100934340087
6. Jasson Johnbosco 23100934340049
7. Dionis Bahati 23100934340071
8. Emmanuel Kipokile 23100934340086 *\

How Synchronization Prevents UI Corruption

Swing components like JTextArea are not thread-safe. Therefore, all updates to the user interface
must beperformed ontheEvent DispatchThread(EDT). Whenbackgroundthreads attempt toupdate the
UI directly, the following problems can occur:

 Raceconditions, wheremultiplethreadstrytoread/writetothesamecomponent
simultaneously.
 Visualglitchesorapplicationcrashes,duetoinconsistentinternalUIstates.
 Deadlocks,whenthreadsblock oneanother tryingtoaccesslockedGUIresources.

Toavoidtheseissues, Javaprovidesseveralsynchronizationmechanisms, whichareappliedinthis program


as follows:

A. SwingUtilities.invokeLater()
Benefits:
- EnsuresallGUIupdatesoccursafelyontheEDT.
- PreventsdirectUImanipulationfromnon-EDT threads.
- AvoidsthreadinterferencewithSwingcomponents.

1
B. synchronizedBlocksforSharedData
Benefits:
- Preventsraceconditionswhensharedvariablesareaccessedconcurrently.
- Guaranteesthat onlyonethreadexecutesablockofcodeatatime.
- MaintainsconsistencyofsharedresourceslikeJTextArea.

2
C. volatileVariablesforThreadCommunication
Benefits:
- Ensureschangesmadebyonethreadareimmediatelyvisibletoothers.
- Preventslocalthreadcachingofstalevalues.
- Suitableforsimplecommunicationwithoutlockingoverhead.

D. CounterSynchronization(ifshared)
Prevents:
- Lostupdatesduetoconcurrentincrements.
- Inconsistentorincorrectcountervalues.
- Raceconditionsduringread-modify-writeoperations.

3
4
2.

class BankAccount {
private int balance = 0;
public synchronized void deposit(int amount, String threadName) {
balance += amount;
System.out.println(threadName + " deposited: " + amount + " | Balance: " + balance);
notifyAll();
}
public synchronized void withdraw(int amount, String threadName) {
while (balance < amount) {
System.out.println(threadName + " waiting to withdraw: " + amount + " | Balance: " +
balance);
try {
wait();
} catch (InterruptedException e) {
System.out.println(threadName + " interrupted while waiting.");
return;
}
}
balance -= amount;
System.out.println(threadName + " withdrew: " + amount + " | Balance: " + balance);
}
}
class DepositThread extends Thread {
private BankAccount account;
private int amount;
public DepositThread(BankAccount account, int amount, String name) {
super(name);
this.account = account;
this.amount = amount;
}
public void run() {
for (int i = 0; i < 3; i++) {
account.deposit(amount, getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(getName() + " interrupted.");
}
}
}
}

class WithdrawThread extends Thread {


private BankAccount account;
private int amount;

public WithdrawThread(BankAccount account, int amount, String name) {


super(name);
this.account = account;
this.amount = amount;
}

public void run() {


for (int i = 0; i < 3; i++) {
account.withdraw(amount, getName());
try {
Thread.sleep(700);
} catch (InterruptedException e) {
System.out.println(getName() + " interrupted.");
}
}
}
}

public class Main {


public static void main(String[] args) {
BankAccount account = new BankAccount();

Thread t1 = new DepositThread(account, 100, "DepositThread-1");


Thread t2 = new WithdrawThread(account, 50, "WithdrawThread-1");
Thread t3 = new WithdrawThread(account, 150, "WithdrawThread-2");
t1.start();
t2.start();
t3.start();
}
}
Explanation of wait(), notify(), notifyAll()
wait(): Releases the lock and causes the thread to wait until another thread calls notify() or notifyAll() on
the same object.
notify(): Wakes up one waiting thread (arbitrary).
notifyAll(): Wakes up all threads waiting on the object's monitor.
In this example:
If the balance is insufficient, a thread waits.
After a deposit, notifyAll() is called to wake up all waiting threads so they can re-check the condition and
possibly proceed.
3.

public class ThreadPriorityDemo {

static class FactorialTask extends Thread {

private int number;

public FactorialTask(ThreadGroup group, String name, int number) {

super(group, name);

this.number = number;

@Override

public void run() {

long result = 1;

for (int i = 1; i <= number; i++) {

result *= i;

for (int j = 0; j < 100000; j++) {

Math.sin(j);

System.out.println(getName() + " [Priority: " + getPriority() + "] - Factorial of " + number + " is
calculated.");

}
}

public static void main(String[] args) {

ThreadGroup group = new ThreadGroup("FactorialGroup");

FactorialTask t1 = new FactorialTask(group, "Thread-High", 20);

FactorialTask t2 = new FactorialTask(group, "Thread-Normal1", 20);

FactorialTask t3 = new FactorialTask(group, "Thread-Normal2", 20);

FactorialTask t4 = new FactorialTask(group, "Thread-Low", 20);

t1.setPriority(Thread.MAX_PRIORITY);

t2.setPriority(Thread.NORM_PRIORITY);

t3.setPriority(Thread.NORM_PRIORITY);

t4.setPriority(Thread.MIN_PRIORITY);

t1.start();

t2.start();

t3.start();

t4.start();

Explanation

Thread Priorities in JVM:

Thread.MAX_PRIORITY = 10

Thread.NORM_PRIORITY = 5

Thread.MIN_PRIORITY = 1

Thread scheduling is managed by the JVM and the OS, so higher-priority threads may get more CPU time,
but execution order is not guaranteed.

The JVM uses a priority-based, preemptive scheduling algorithm but delegates thread execution to the
host OS. On platforms like Windows, priorities are respected to a degree, but may not enforce strict
order. Therefore, thread priorities should be used for hints rather than control mechanisms.
OUTPUT
4.
class Matrix<T extends Number> {
private T[][] data;

public Matrix(T[][] data) {


if (data.length != 2 || data[0].length != 2) throw new
IllegalArgumentException("Only 2x2 matrix allowed");
this.data = data;
}

public Matrix<Double> add(Matrix<T> other) {


Double[][] result = new Double[2][2];
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
result[i][j] = this.data[i][j].doubleValue() +
other.data[i][j].doubleValue();
return new Matrix<>(result);
}

public void print() {


for (T[] row : data)
System.out.println(java.util.Arrays.toString(row));
}

public static void main(String[] args) {


Double[][] m1 = {{1.2, 2.3}, {3.4, 4.5}};
Double[][] m2 = {{5.6, 6.7}, {7.8, 8.9}};
Matrix<Double> matrix1 = new Matrix<>(m1);
Matrix<Double> matrix2 = new Matrix<>(m2);

Matrix<Double> sum = matrix1.add(matrix2);


sum.print();
}
}
Restriction
Inspired by the Stats class for numeric constraints using T extends
Number. Java generics don't support primitive types directly (e.g.,
int, double), hence boxed types are used.
5.

import java.util.Arrays;

class Student implements Comparable<Student> {


String name;
int grade;

public Student(String name, int grade) {


this.name = name;
this.grade = grade;
}

public int compareTo(Student other) {


return this.grade - other.grade;
}

public String toString() {


return name + ": " + grade;
}
}

class SortValidator {
public static <T extends Comparable<T>> void sortAndValidate(T[] array) {
for (T item : array)
if (!item.getClass().equals(array[0].getClass()))
throw new IllegalArgumentException("Inconsistent types in array");
Arrays.sort(array);
System.out.println(Arrays.toString(array));
}

public static void main(String[] args) {


Integer[] nums = {3, 1, 4, 2};
String[] words = {"banana", "apple", "cherry"};
Student[] students = {
new Student("Alice", 88),
new Student("Bob", 72),
new Student("Charlie", 95)
};

sortAndValidate(nums);
sortAndValidate(words);
sortAndValidate(students);
}
}
Explanation: Based on printArray, we ensure type consistency with runtime checks because
generics use type erasure.
6.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TextFieldApp {


public static void main(String[] args) {
JFrame frame = new JFrame("TextField Example");
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();

JTextField textField = new JTextField(15);


JButton button = new JButton("Show Text");
JCheckBox checkBox = new JCheckBox("Enable TextField");

checkBox.setSelected(true);

button.addActionListener(e -> JOptionPane.showMessageDialog(frame,


textField.getText()));
checkBox.addItemListener(e -> textField.setEnabled(e.getStateChange() ==
ItemEvent.SELECTED));

gbc.gridx = 0; gbc.gridy = 0; frame.add(textField, gbc);


gbc.gridy = 1; frame.add(button, gbc);
gbc.gridy = 2; frame.add(checkBox, gbc);

frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Explanation: Demonstrates interaction between components using listeners. Inspired by
SwingFirstExample and CheckBoxExample.

7.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DrawingApp extends JPanel {
private int x, y;
private boolean dragging = false;
public DrawingApp() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
x = e.getX(); y = e.getY(); dragging = false;
repaint();
}
public void mousePressed(MouseEvent e) {
dragging = true;
}
public void mouseReleased(MouseEvent e) {
dragging = false;
}
});

addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
if (dragging) {
x = e.getX(); y = e.getY();
repaint();
}
}
});
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (dragging) {
g.setColor(Color.YELLOW);
g.fillRect(x - 10, y - 10, 20, 20);
} else {
g.setColor(Color.GREEN);
g.fillOval(x - 10, y - 10, 20, 20);
}
}

public static void main(String[] args) {


JFrame frame = new JFrame("Drawing App");
frame.add(new DrawingApp());
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Explanation: MouseAdapter simplifies listener code. Easier than implementing full
MouseListener.

8.
import javax.swing.*;

public class SyncTextAreaApp {


private static final JTextArea textArea = new JTextArea();

public static void main(String[] args) {


JFrame frame = new JFrame("Threaded JTextArea");
frame.add(new JScrollPane(textArea));
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

Runnable counterTask = () -> {


int count = 0;
while (true) {
synchronized (textArea) {
textArea.append("Count: " + count++ + "\n");
}
try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
}
};

Runnable timestampTask = () -> {


while (true) {
synchronized (textArea) {
textArea.append("Time: " + new java.util.Date() + "\n");
}
try { Thread.sleep(2000); } catch (InterruptedException ignored) {}
}
};

new Thread(counterTask).start();
new Thread(timestampTask).start();
}
}
Explanation: Ensures thread safety via synchronization to avoid race conditions.

9.
import javax.swing.*;
import java.awt.event.*;

public class MenuApp {


public static void main(String[] args) {
JFrame frame = new JFrame("Menu Example");
JMenuBar menuBar = new JMenuBar();

JMenu fileMenu = new JMenu("File");


JMenuItem open = new JMenuItem("Open");
JMenuItem exit = new JMenuItem("Exit");
fileMenu.add(open);
fileMenu.add(exit);

JMenu editMenu = new JMenu("Edit");


JMenu formatSubMenu = new JMenu("Format");
JMenuItem bold = new JMenuItem("Bold");
JMenuItem italic = new JMenuItem("Italic");
formatSubMenu.add(bold);
formatSubMenu.add(italic);
editMenu.add(formatSubMenu);

menuBar.add(fileMenu);
menuBar.add(editMenu);
frame.setJMenuBar(menuBar);

ActionListener menuAction = e -> JOptionPane.showMessageDialog(frame,


e.getActionCommand() + " clicked");
open.addActionListener(menuAction);
exit.addActionListener(e -> System.exit(0));
bold.addActionListener(menuAction);
italic.addActionListener(menuAction);

frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Explanation: Uses ActionListeners for menu items. Matches Swing’s MVC where JMenuBar
(View) notifies ActionListener (Controller) to handle logic.
QN:

Implement a generic class Buffer<T> that acts as a bounded buffer for a producer-consumer
scenario. The producer thread adds items of type T (e.g., String), and the consumer thread
removes them, using wait() and notifyAll() for synchronization. Test with a String buffer of size
5, and ensure thread safety. Explain how the document’s inter-thread communication and
generics examples influenced your design.

SOLUTION

Consider the snipped code below;

Buffer<> implementation
Producer Threads& Consumer Threads

Output
Explanation;

The Buffer class uses an Array The “Buffer” class uses an “Array List<Integer>”to store items with a fixed
capacity. The producer thread adds one integer (`42`) to the buffer and prints confirmation. The consumer thread
retrieves the integer and also prints a message. ‘Wait () ` and `notify All () ` ensure that threads wait and notify each
other properly. The output confirms the production and consumption of a single integer item safely. List<Integer>
to store items with a fixed capacity. The producer thread adds one integer (42) to the buffer and
prints confirmation. The consumer thread retrieves the integer and also prints a message. Wait ()
and notify All () ensure that threads wait and notify each other properly. The output confirms the
production and consumption of a single integer item safely.

According to the output;

Produced: 42 – The producer thread adds the integer 42 to the buffer.

Producer finished – Producer thread completes after one insertion.

Consumed: 42 – The consumer thread takes the item from the buffer.

Consumer finished – Consumer thread completes after one retrieval.

You might also like