Why is the ArrayList not updated in the following example? - java

I am using the JNativeHook library.
An instance of GlobalKeyListener starts listening to Keystrokes and adds them to arrayList1; problem is that the arrayList1 does not seem to get updated (list1itemCount does never get bigger then 0) when accessing it over the infinite while(true) loop in the Child class. Why is that and what must I do to achieve that?
public class Child {
public static void main(String[] args) {
// Get the logger for "org.jnativehook" and set the level to warning.
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalKeyListener globalkeylistener = new GlobalKeyListener();
GlobalScreen.addNativeKeyListener(globalkeylistener);
Connection conn;
while(true){
int list1itemCount = globalkeylistener.arrayList1.size();
if (list1itemCount >= 4)
System.out.println(list1itemCount);
}
}
}
GlobalKeyListener Class:
public class GlobalKeyListener implements NativeKeyListener {
ArrayList<Class1> arrayList1 = new ArrayList<>();
public ArrayList<Class1> listing() {
return arrayList1;
}
public void nativeKeyPressed(NativeKeyEvent e) {
arrayList1.add(new Class1(e.getKeyCode(), 1));
}
public void nativeKeyReleased(NativeKeyEvent e) {
arrayList1.add(new Class1(e.getKeyCode(), 0));
}
public void nativeKeyTyped(NativeKeyEvent e) {
}
}

This is a multithreading issue. The keyEvent updates occur on a different thread, and your while(true) won't update. Also, the ArrayList itself is not threadsafe as you've written it.
It would be better to synchronize on something (the easiest, not necessarily best) thing is the key listener itself, and have it wait until the update occurs and then notify. Here's the modified code:
GlobalKeyListener.java
public class GlobalKeyListener implements NativeKeyListener {
ArrayList<Class1> arrayList1 = new ArrayList<>();
public ArrayList<Class1> listing() {
return arrayList1;
}
public void nativeKeyPressed(NativeKeyEvent e) {
synchronized(this) {
arrayList1.add(new Class1(e.getKeyCode(), 1));
this.notifyAll();
}
}
public void nativeKeyReleased(NativeKeyEvent e) {
synchronized(this) {
arrayList1.add(new Class1(e.getKeyCode(), 0));
this.notifyAll();
}
}
public void nativeKeyTyped(NativeKeyEvent e) {
}
}
Child.java
public class Child {
public static void main(String[] args) throws InterruptedException {
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalKeyListener globalkeylistener = new GlobalKeyListener();
GlobalScreen.addNativeKeyListener(globalkeylistener);
synchronized(globalkeylistener) {
while(true){
int list1itemCount = globalkeylistener.arrayList1.size();
if (list1itemCount >= 4) {
System.out.println(list1itemCount);
}
globalkeylistener.wait();
}
}
}
}

Related

Sequence of robot's move using multithreading

I have a code and I want to ensure the order in which the robot's legs move using wait() and notify(). Here is the code:
public class Leg implements Runnable {
private final Object monitor = new Object();
private final String name;
public Leg(String name) {
this.name = name;
}
#Override
public void run() {
while (true) {
synchronized (monitor) {
move();
monitor.notify();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void move() {
System.out.println(name);
}
public static void main(String[] args) {
CompletableFuture.allOf(
CompletableFuture.runAsync(new Leg("left")),
CompletableFuture.runAsync(new Leg("right"))
).join();
}
}
Right now the output is the below:
left
right
// and then it stops moving.
I want the code continue moving (not only once). That's why it's interesting for me what am I doing wrong?
You have 2 Leg object with 2 threads to process, for each thread you have a monitor object, so when you use notify and wait, it just effects to one thread (which thread is running currently):
synchronized (monitor) {
move();
monitor.notify(); // notify current thread, it's no meaning
try {
monitor.wait(); // current thread will block here and there is no thread wake up it
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Maybe it's what you need:
import java.util.concurrent.CompletableFuture;
public class Leg implements Runnable {
private final String name;
private Leg nextLeg;
private volatile boolean active;
public Leg(String name) {
this.name = name;
}
public void setNextLeg(Leg nextLeg) {
this.nextLeg = nextLeg;
}
public void active() {
synchronized (this) {
this.active = true;
notify();
}
}
#Override
public void run() {
while (true) {
try {
synchronized (this) {
while (!active) {
wait();
}
move();
active = false;
nextLeg.active();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
private void move() {
System.out.println(name);
}
public static void main(String[] args) {
Leg left = new Leg("left");
Leg right = new Leg("right");
left.setNextLeg(right);
right.setNextLeg(left);
left.active();
CompletableFuture.allOf(
CompletableFuture.runAsync(left),
CompletableFuture.runAsync(right)
).join();
}
}

how to call a method with multiple threads

I have a method sendMail(list). This method will send the mails to the recipients which are there in the list.
public void sendMail(List<DTO> dto) {
for(DTO individualObject: dto) {
bulkMailSender.sendSimpleMessage(individualObject.getEmail(),masterDetails.getMailSubject() , content, masterDetails.getMailFrom(), individualObject);
try {
TimeUnit.MINUTES.sleep(Long.parseLong(individualObject.getTimegap().trim()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I have this kind of method. I want to run this method Thread based, when one thread is executing the mails, I should allow the other thread to access sendMail and send simultaneously together. Each and every individualObject contains it's own sleep time.
How can I make it worked with the multiple threads.
Let's take an example
import java.util.concurrent.TimeUnit;
public class SleepClass {
public static void main(String[] args) {
SleepClass s= new SleepClass();
s.m1(10000);
s.m1(20000);
}
public void m1(int time) {
for(int i = 0; i< 3; i++) {
System.out.println(i);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
In the above example I have a regular method and it is executing one by one. How can make it simultaneous execution
if you need simultaneous execution and each time new thread you can find the solution here
public class SleepClass {
public static void main(String[] args) {
SleepClass s= new SleepClass();
s.m2(500);
s.m2(1000);
}
public void m2(int time) {
SleepClass s= new SleepClass();
new Thread(() -> {
s.m1(time);
}).start();
}
public void m1(int time) {
for(int i = 0; i<= 10; i++) {
System.out.println(i);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You have to put your logic in a Runnable and launch it using new Thread(runnable).start().
To pass parameters to each runnable define them as class variables so you can pass them via the constructor and use them in the run method:
public class SleepClass {
public static void main(String[] args) {
SleepClass s= new SleepClass();
s.m1(10000);
s.m1(20000);
}
public void m1(int time) {
for(int i = 0; i< 3; i++) {
new Thread(new Launcher(i,time)).start();
}
}
public class Launcher implements Runnable {
int i;
int time;
public Launcher(int i, int time) {
this.i=i;
this.time=time;
}
#Override
public void run() {
System.out.println(i);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Why am I not getting synchronized access in my code?

class Caller extends Thread
{
String s;
Caller(String s)
{
this.s=s;
}
void call(String msg)
{
synchronized (this)
{
System.out.print("["+msg);
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
System.out.println("]");
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
public void run()
{
call(s);
}
}
public class SynchronisedBlock {
public static void main(String[] args) {
Caller c=new Caller("hi");
Caller c1=new Caller("li");
Caller c2=new Caller("wi");
c.start();
c1.start();
c2.start();
}
}
public class SynchronisedBlock {
public static void main(String[] args) {
Caller c=new Caller("hi");
Caller c1=new Caller("li");
Caller c2=new Caller("wi");
c.start();
c1.start();
c2.start();
}
}
I am trying to get synchronized access to call() using synchronized block but not getting that feature.When I am putting call() method in another class then I am getting the required functionality but not in this code. What am I missing? Can anyone tell me why? Thanx in advance.
As #svasa has stated, you need to have a common synchronizing object.
The simplest working example for your code would be to use a shared lock object. Also, the lock is final to prevent it from being replaced somewhere else in the code, you would end up synchronizing on different objects. (thanks to #P.J.Meisch):
class Caller extends Thread {
String s;
private static final Object lock = new Object();
Caller(String s) {
this.s = s;
}
void call(String msg) {
synchronized (lock) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(e);
}
System.out.println("]");
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(e);
}
}
}
public void run() {
call(s);
}
If your run method were in a Runnable like it's supposed to be, instead of a Thread, which it's not, then you could pass the same Runnable instance to each thread and this would work as a synchronization object reference.

Producer consumer variant java BlockingQueues

I'm working on a variant of the producer consumer problem in Java. I have a producer thread creating objects, that are put into an priority blocking queue, and then passed into the main container, the controller, which is a bounded buffer.
The reason for the queue is that when the main container has a certain % of Object A, it will only accept objects of type B, and some other scenarios that we have been asked to look at.
I'm having trouble figuring out what is going wrong with the code, the debugger is just jumping from in.offer in InQueue, and in.push in Producer. Any direction or advice would be appreciated.
import java.util.concurrent.PriorityBlockingQueue;
public class InQueue implements Runnable {
Controller c;
private PriorityBlockingQueue in;
public InQueue(Controller c) {
this.c = c;
in = new PriorityBlockingQueue();
}
public void push(C c) {
in.offer(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
C temp = (C) in.take(); //will block if empty
c.arrive(temp);
} catch (InterruptedException e) {} // TODO
}
}
}
public class Controller {
private BoundedBuffer buffer;
private int used;
Controller(int capacity) {
this.buffer = new BoundedBuffer(capacity);
used = 0;
}
public void arrive(C c) {
try {
buffer.put(c);
used++;
} catch (InterruptedException e) { } //TODO
}
public C depart() {
C temp = null; //BAD IDEA?
try {
temp = (C)buffer.take();
used--;
} catch (InterruptedException e) { } //TODO
return temp; //could be null
}
}
Your code is not compiling because of the wrong way your using generics. Another thing is that there is no default implementation of BoundedBuffer. Below I made a working implementation for the producer - consumer problem below with blocking queues. Have a look and correct your mistakes.
package concurrency;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Producer<T> {
private final BlockingQueue<T> queue;
private final Consumer consumer;
private static volatile boolean isShutdown;
private final static Object lock = new Object();
public Producer() {
this.queue = new LinkedBlockingQueue<T>();
this.consumer = new Consumer();
}
public void start() {
consumer.start();
}
public void stop() {
synchronized (lock) {
isShutdown = true;
}
consumer.interrupt();
}
public void put(T obj) throws InterruptedException {
synchronized (lock) {
if (isShutdown)
throw new IllegalStateException("Consumer Thread is not active");
}
queue.put(obj);
}
private class Consumer extends Thread {
public void run() {
while (true) {
synchronized (lock) {
if (isShutdown)
break;
}
T t = takeItem();
// do something with 't'
if(t!=null)
printItem(t);
}
}
private void printItem(T t) {
System.out.println(t);
}
private T takeItem() {
try {
return queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return null;
}
}
public static void main(String[] args) throws InterruptedException {
Producer<Integer> producer = new Producer<Integer>();
producer.start();
for (int i = 0; i <20; i++) {
producer.put(i);
if (i >= 7)
Thread.sleep(500);
}
producer.stop();
}
}

Concurrency - why does the last instruction in this function never execute?

I have this code:
private void doSomething() throws InterruptedException {
WorkerThread w= new WorkerThread(this);
w.start();
synchronized (synchObj) {
while (!isDone) {
synchObj.wait();
}
}
System.out.println("End");
}
Where the calling class implements a method that calls notifyAll() on synchObj when WorkerThread instance is done. Everything works pretty much as expected except the final call to System.out.println("End"); is never called. Why is that?
Edit: Here's the rest of the code:
public class App implements Notifee {
private boolean isDone = false;
private final Object synchObj = new Object();
/**
* #param args
*/
public static void main(String[] args) {
App app = new App();
for (int i = 0; i < 5; i++) {
try {
app.doSomething();
} catch (InterruptedException e) {
System.err.println("Didn't even start");
e.printStackTrace();
}
}
}
private void doSomething() throws InterruptedException {
WorkerThread w= new WorkerThread(this);
w.start();
synchronized (synchObj) {
while (!isDone) {
synchObj.wait();
}
}
System.out.println("End");
}
#Override
public void letMeKnow() {
synchronized (synchObj) {
synchObj.notifyAll();
}
}
}
public class WorkerThread extends Thread {
private Notifee n;
public WorkerThread(Notifee n){
this.n = n;
}
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
n.letMeKnow();
}
}
You are never setting isDone to true. Also you should make it volatile. You probably should add:
#Override
public void letMeKnow() {
isDone = true;
synchronized (synchObj) {
synchObj.notifyAll();
}
}
Edit: If you want to just wait for the worker thread to finish call:
w.join();

Categories