Background
Relevant concepts
What is multithreading
We call the components of the Program threads. In other words, a thread is a lightweight Process in a program.
Multithreading is a Java feature that allows multiple parts of a program (i.e., threads) to execute concurrently in order to maximize CPU utilization.
Multithreading is a Java feature that allows concurrent execution of two or more parts of a program for maximum utilization of CPU. Each part of such program is called a thread. So, threads are light-weight processes within a process.
– www.geeksforgeeks.org/multithread…
Thread state
polling
Samples
Polling is a process called Polling, in which a loop executes a certain logical judgment and does not Polling until the judgment condition is true. Polling is a waste of CPU resources.
The process of testing a condition repeatedly till it becomes true is known as polling.Polling is usually implemented with the help of loops to check whether a particular condition is true or not. If it is true, certain action is taken. This waste many CPU cycles and makes the implementation inefficient.
– www.geeksforgeeks.org/inter-threa…
An example implementation of polling is provided below.
The Message:
IsAvailable the initial value is false. When set to true, the polling body is executed.
Be careful to use thread-safe AtomicBoolean; if you use Boolean, you can expect unexpected results in multithreaded situations.
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.atomic.AtomicBoolean;
@Setter
@Getter
public class Message {
private AtomicBoolean isAvailable = new AtomicBoolean(false);
private String msg;
public Message(String str) {
this.msg = str; }}Copy the code
PollingWaiter:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class PollingWaiter implements Runnable {
private Message msg;
public PollingWaiter(Message m) {
this.msg = m;
}
@Override
public void run(a) {
String name = Thread.currentThread().getName();
synchronized (msg) {
int count = 0;
System.out.println(name + " : waiter starting at time: " + LocalDateTime.now().format(DateTimeFormatter.ISO_TIME));
while(! msg.getIsAvailable().get()) { count++; } System.out.println(name +" : msg is available at time: " + LocalDateTime.now().format(DateTimeFormatter.ISO_TIME));
System.out.println(name + " : msg is available after count: " + count);
System.out.println(name + " : processed: "+ msg.getMsg()); }}}Copy the code
Perform tests:
After sleeping for 3 seconds, poll the internal code.
import java.util.concurrent.atomic.AtomicBoolean;
public class WaitNotifyTest {
public static void main(String[] args) {
testPolling();
}
public static void testPolling(a) {
Message msg = new Message("process it");
PollingWaiter waiter = new PollingWaiter(msg);
new Thread(waiter, "PollingWaiter").start();
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
msg.setIsAvailable(new AtomicBoolean(true));
System.out.println("over"); }}Copy the code
Output result:
PollingWaiter : waiter starting at time: 14:26:08.482
over
PollingWaiter : msg is available at time: 14:26:11.402
PollingWaiter : msg is available after count: -69547606
PollingWaiter : processed: process it
Copy the code
Wait and notify
In addition to polling, Java implements communication between threads through wait and Notify mechanisms. Wait causes a thread holding an object to wait and block, while notify causes a thread holding an object to regain CPU resources and run again.
Because the wait and notify methods are implemented in the java.lang.Object class, they are available to all subclasses.
The wait and notify related methods need to be executed in a synchronized block.
Methods to introduce
Here is a brief overview of these methods:
- wait()
Wait () causes the current thread to change from executing to waiting until another thread executes notify() or notifyAll() on the current object.
- wait(long timeout)
The difference with wait() is that if the notify() or notifyAll() has not been performed by the previous object after the timeout, the thread automatically starts execution.
Note that executing wait(0) has the same effect as waiting ().
- wait(long timeout, int nanos)
Compared to wait(long timeout), this method provides a higher precision for waiting timeout Settings, down to nanoseconds.
1 millisecond = 1,000,000 nanoseconds.
- notify()
For all threads waiting on the monitor for this object, performing notify() wakes up a random thread.
- notifyAll()
In contrast to notify(), this method wakes up all the monitor threads waiting for the object.
The sample
Based on the above sample code, add the following code implementation.
Waiter:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg=m;
}
@Override
public void run(a) {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" : waiting to get notified at time:"+ LocalDateTime.now().format(DateTimeFormatter.ISO_TIME));
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" : waiter thread got notified at time:"+LocalDateTime.now().format(DateTimeFormatter.ISO_TIME));
//process the message now
System.out.println(name+" : processed: "+msg.getMsg()); }}}Copy the code
Notifier:
public class Notifier implements Runnable {
private boolean isAll = true;
private Message msg;
public Notifier(Message msg, boolean isAll) {
this.msg = msg;
this.isAll = isAll;
}
@Override
public void run(a) {
String name = Thread.currentThread().getName();
System.out.println(name + " started");
try {
Thread.sleep(3000);
synchronized (msg) {
System.out.println(name + " : got the msg : "+msg.getMsg());
msg.setMsg(name + " : Notifier work done");
if (isAll) {
msg.notifyAll();
} else{ msg.notify(); }}}catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code
WaitNotifyTest:
import java.util.concurrent.atomic.AtomicBoolean;
public class WaitNotifyTest {
public static void main(String[] args) {
//testPolling();
testNotify();
//testNotifyAll();
}
public static void testPolling(a) {
Message msg = new Message("process it");
PollingWaiter waiter = new PollingWaiter(msg);
new Thread(waiter, "PollingWaiter").start();
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
msg.setIsAvailable(new AtomicBoolean(true));
System.out.println("over");
}
public static void testNotify(a) {
Message msg = new Message("process it");
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Waiter waiter2 = new Waiter(msg);
new Thread(waiter2, "waiter2").start();
Notifier notifier = new Notifier(msg, false);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
public static void testNotifyAll(a) {
Message msg = new Message("process it");
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Waiter waiter2 = new Waiter(msg);
new Thread(waiter2, "waiter2").start();
Notifier notifier = new Notifier(msg, false);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started"); }}Copy the code
If two threads execute wait at the same time, only one thread wakes up after notify, and the other thread is stuck waiting indefinitely.
Links
The warehouse address
-
Github.com/javastudyde…
-
See the complete sample code:
Github.com/javastudyde…
Refer to the link
-
www.geeksforgeeks.org/inter-threa…
-
www.baeldung.com/java-wait-n…
-
www.journaldev.com/1037/java-t…