How to count incoming messages from a "stream" in Java? - java

So I'm receiving numerous messages from a stream - well, it's not a stream per se, it's really a method that's fired off when a message is received - and I would like to count the number of messages received in 10 seconds.
Here's what I have so far:
package com.example.demo;
import java.net.URI;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
public class ExampleClient extends WebSocketClient {
private float messagesRecievedCount;
public ExampleClient(URI serverUri) {
super(serverUri);
System.out.println("Created object");
setMessagesRecievedCount(0);
}
#Override
public void onOpen(ServerHandshake serverHandshake) {
System.out.println("Connection established!");
}
#Override
public void onMessage(String s) {
setMessagesRecievedCount(getMessagesRecievedCount() + 1);
}
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
long ten = System.currentTimeMillis() + 1000;
while(System.currentTimeMillis() < ten) {
end = getMessagesRecievedCount();
}
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
public float getMessagesRecievedCount() {
return messagesRecievedCount;
}
public void setMessagesRecievedCount(float messagesRecievedCount) {
this.messagesRecievedCount = messagesRecievedCount;
}
}
I have a global variable messagesRecievedCount which keeps a running count of messages received from a websocket stream. Whenever a message is received the onMessage() method is fired and it updates the message count. I want to count the number of messages received in 10 seconds (and extrapolate it to a minute) - for which I have the getMessagesPerMinute().
Obviously the way I'm doing it is not smart - it's blocking and the count of messages after 10 seconds is the same (when actually it isn't, I've actually received 20 messages). I feel like I should be doing threads but I don't know how to go about it. What would you suggest? I'm really new to this and just tinkering around.
This is the main class where I'm calling ExampleClient.java from:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.WebSocketSession;
import java.net.URI;
import java.net.URISyntaxException;
#SpringBootApplication
public class DemoApplication {
private WebSocketSession clientSession;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public DemoApplication () throws URISyntaxException {
ExampleClient c = new ExampleClient( new URI( "wss://example.com/" ) );
c.connect();
c.getMessagesPerMinute();
}
}
The c.connect() establishes the connection and the onMessage() is triggered soon after!

Your code actully runs fo 1 second (1000ms, I don't know if this is a typo or a voluntary simplification). One other problem is that it calls end = getMessagesRecievedCount(); repeatedly inside a while loop, while you actually need only the starting and final value. A way to solve this would be using Thread.sleep() (if you never need to cancel the counting midway):
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
try{
Thread.sleep(10000);
}
catch(InterruptedException e){
System.out.println("do something");
}
end = getMessagesRecievedCount();
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
For blocking the important thing is that this code runs in a different thread that the one updating the value of messagesRecievedCount or doing other things that you may want to do in the meanwhile, so calling it inside a new thread is probably the best solution. I'm not familiar with the framework you are using so it may be already using different threads that better suit this purpose.
If you intend to do something more with the variable messagesRecievedCount some synchronization would be required, but for an estimate of the number of messages for minute this should be good enough.
Here is some test code I used that you can hopefully adapt to better suit your case and play with to pinpoint the problem. The difference is quite constant in this case, but the values are clearly updated. Making the ExampleClient instance public is a shortcut which should probaby be avoided in the actual code.
public class Test{
public static ExampleClient example=new ExampleClient();
public static void main(String[] args){
Thread a=new MessagesPerTenSecondFetcher();
Thread b=new MessagesPerTenSecondFetcher();
Thread c=new MessagesPerTenSecondFetcher();
Thread d= new MessageProducer();
a.start();
d.start();
b.start();
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
System.out.println("do something");
}
c.start();
}
}
class ExampleClient {
private float messagesRecievedCount;
public void onMessage(String s) {
setMessagesRecievedCount(getMessagesRecievedCount() + 1);
}
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
try{
Thread.sleep(10000);
}
catch(InterruptedException e){
System.out.println("do something");
}
end = getMessagesRecievedCount();
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
public float getMessagesRecievedCount() {
return messagesRecievedCount;
}
public void setMessagesRecievedCount(float messagesRecievedCount) {
this.messagesRecievedCount = messagesRecievedCount;
}
}
class MessagesPerTenSecondFetcher extends Thread{
#Override
public void run(){
Test.example.getMessagesPerMinute();
}
}
class MessageProducer extends Thread{
#Override
public void run(){
for(int i =0; i<100;i++){
Test.example.onMessage("a");
try{
Thread.sleep(130);
}
catch(InterruptedException e){
System.out.println("do something");
}
}
}
}

Related

I can't save data into my firebase database [duplicate]

This question already has answers here:
wait until all threads finish their work in java
(17 answers)
Closed 6 years ago.
Say I'm using a HTTP requests library for downloading files. This library uses threads inside. Now, I want to wait on the main thread until other threads complete their execution.
All the other solutions that I found by googling only work if I have access to the Thread variables that were used in the library. But these are not accessible to me.
Here's what i'm using currently:
package smartzero.eightnoteight.testfirebase;
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("email: ");
String email = in.nextLine();
System.out.print("password: ");
String password = in.nextLine();
Firebase fb = new Firebase("https://nullform.firebaseio.com");
fb.authWithPassword(email, password, new AuthResultHandler());
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static class AuthResultHandler implements Firebase.AuthResultHandler {
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("authentication successful");
String uid = authData.getUid();
new RunTests(uid);
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
System.out.println("authentication failed.");
}
}
}
PS: i'm testing firebase using firebase-client-jvm on my pc.
You should use the events provided by Firebase:
fb.authWithPassword(email, password, new AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
//do something if authentication successful
}
#Override
public void onAuthenticationError(FirebaseError error) {
//handle error
}
});
You could, if you really want to wait in the main do this:
void main(String[] args) {
boolean finished = false;
fb.authWithPassword(email, password, new AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
finished = true;
}
});
while (!finished){
Thread.sleep(1);
}
}
Thats more of a pseudocode. It doesnt catch the interrupted exception and blocks forever if there is an error (onAuthenticationError). Also i would not recommend this. Busy waiting is almost never a good idea.
On non-Android runtimes the Firebase Java client uses daemon threads, which will not prevent a process from exiting. You must handle this using a CountdownLatch or a Semaphore.
CountdownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
Your code on it:
package smartzero.eightnoteight.testfirebase;
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("email: ");
String email = in.nextLine();
System.out.print("password: ");
String password = in.nextLine();
in.close();
Firebase fb = new Firebase("https://nullform.firebaseio.com");
CountDownLatch done = new CountDownLatch(1);
fb.authWithPassword(email, password, new Firebase.AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("authentication successful");
done.countDown();
}
#Override
public void onAuthenticationError(FirebaseError error) {
System.out.println("authentication failed.");
done.countDown();
}
});
done.await();
}
}
Semaphore
It is used to control the number of concurrent threads that are using a resource. You could think of it as tickets to use a resource. You set the number of tickets available when you create it, and when acquire() is called with no tickets left, your process will wait for one to become available (on a release() call). On your code it is being created with zero "tickets" available:
package smartzero.eightnoteight.testfirebase;
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.Scanner;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("email: ");
String email = in.nextLine();
System.out.print("password: ");
String password = in.nextLine();
in.close();
Firebase fb = new Firebase("https://nullform.firebaseio.com");
Semaphore semaphore = new Semaphore(0);
fb.authWithPassword(email, password, new Firebase.AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("authentication successful");
semaphore.release();
}
#Override
public void onAuthenticationError(FirebaseError error) {
System.out.println("authentication failed.");
semaphore.release();
}
});
semaphore.acquire();
}
}
A CountdownLatch is really good for having one thread wait for one or more threads to complete one or more tasks before proceeding.
First, create the countdown latch with count of n, where n is the number events you want to wait on. Next, give the latch to the thread or threads doing the work. After that, the thread that should wait calls await() on the latch, and simultaneously the other threads begin working. When each of the worker threads is done, they call countdown() on the latch. When the latch counter hits zero, the waiting thread (or possibly threads) will unblock.

How to synchronize the threads in the time Java

I study a thread and trying make a timer using thread. To the main thread wrote a time
public class A {
public static void main(String[] args) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please, write the time in ms");
long time = Long.parseLong(reader.readLine());
B thread = new B();
int timer = 0;
try {
thread.start();
Thread.sleep(time);
timer=thread.stop();
}
catch(InterruptedException e) {
System.out.println("Oh....");
}
System.out.println("Result is "+timer);
}
}
and every millisecond program write a name of specific millisecond in child thread.
public class B implements Runnable {
private volatile boolean running=true;
private int timer=0;
Thread thread;
public B() {
thread = new Thread(this);
}
public void run() {
while (running) {
System.out.println(timer);
timer++;
try {
Thread.sleep(1);
}
catch(InterruptedException e) {
System.out.println("B");
}
}
}
public int stop() {
running = false;
return timer;
}
public void start() {
thread.start();
}
}
But when try with parameter 50 get the result 37. I want understand how to synchronize it in the time. Can you explain me how to do it correct?
When time is over just set the variable running to false,it will end the while loop and the child thread will also be finished.
So after below line, try to set running variable to false.(provide some setter method or may be in constructor argument)
Thread.sleep(time);
You are forgetting that all the statements other than Thread.sleep(1) also take time to execute. Most notably the System.out.println(timer): this is an I/O operation and whenever such an operation takes place, it usually sucks time (printing to screen makes the program wait for this blocking I/O operation to complete).
But I like to demonstrate a more subtle assumption: you also assume that when thread.start() returns, B.run() is executing. This is not the case, as is demonstrated in the following little program:
import java.util.concurrent.TimeUnit;
public class ThreadTimer implements Runnable {
public static void main(String[] args) {
ThreadTimer tt = new ThreadTimer();
long afterStart = 0L;
new Thread(tt).start();
afterStart = System.nanoTime();
println("After start: " + afterStart);
try {
Thread.sleep(100L);
} catch (Exception e) {
e.printStackTrace();
}
long deltaStart = tt.realStart - afterStart;
println("Delta start: " + deltaStart);
long deltaStartMs = TimeUnit.NANOSECONDS.toMillis(deltaStart);
println("Delta start ms.: " + deltaStartMs);
}
public long realStart;
#Override
public void run() {
realStart = System.nanoTime();
println("Real start : " + realStart);
}
private static void println(String msg) {
System.out.println(msg);
}
}
On my system this shows:
After start: 40062314666459
Real start : 40062314706827
Delta start: 40368
Delta start ms.: 0
Which means a little bit of time was lost. I'm sure that if you measure how long it takes to perform System.out.println(timer), you will see more little bits of time lost. All these little bits eventually add up to quite a chunk of time not accounted for.
On a final note: System.nanoTime() and System.currentTimeMillis() also take time to execute (it takes time to measure the time).

Bukkit conversation fails sleeping

I'm trying to use a Bukkit conversation, which already works, yet, when I use TimeUnit.SECONDS.sleep(integer-value), it works once, and then it fails with this error in console: java.lang.InterruptedException: sleep interrupted
When a prompt has been shown and the next is going to be shown the method acceptInput is called. In the first prompt it works all fine, in the other prompts, which are called out of this prompt (the prompt calls a new instance of itself). All works fine except the sleep part. Any ideas to fix this?
Here is my code:
package dbx12.Test1.Tutorial.Prompts;
import java.util.concurrent.TimeUnit;
import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.Prompt;
import org.bukkit.entity.Player;
public class Text implements Prompt {
#Override
public Prompt acceptInput(ConversationContext context, String input) {
int thisPrompt = (int) context.getSessionData("step");
context.setSessionData("step", thisPrompt+1);
Player p = (Player) context.getForWhom();
boolean type;
try {
TimeUnit.SECONDS.sleep(dbx12.Test1.Utils.Prompt_List.delay.get(thisPrompt));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace(); //DEBUG
}
try {
type = dbx12.Test1.Utils.Prompt_List.promptType.get(thisPrompt+1);
} catch (Exception e) {
return new Finish();
}
if(dbx12.Test1.Utils.Prompt_List.hasLocation.get(thisPrompt+1) == true)
p.teleport(dbx12.Test1.Utils.Prompt_List.location.get(thisPrompt+1));
if(type==true)
{
System.out.println("return a text");
return new Text();
}
else
{
System.out.println("return a interaction");
return new Interaction();
}
}
#Override
public boolean blocksForInput(ConversationContext context) {
return false;
}
#Override
public String getPromptText(ConversationContext context) {
return dbx12.Test1.Utils.Prompt_List.promptText.get(context.getSessionData("step"));
}
}
sleep will cause your entire server to stop doing anything for x seconds. Instead of sleep, use a SyncDelayedTask:
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
public void run(){
//what you want to do here
}
},delayInSeconds * 20);
so, lets say for example you wanted to send test1 to the server, then test2 to the server 5 seconds later, you could use:
int repeats;
public void sendMessages(){
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
public void run(){
if(repeats == 0){ //if it's the first time running
Bukkit.getServer.broadcastMessage("test1");
repeats++; //add to repeats
sendMessages(); //call the method again
}
else if(repeats == 1){ //if it is the second time being called
Bukkit.getServer.broadcastMessage("test2");
}
}
},5 * 20);//wait 5 seconds
so with the above code, you could make a method like this:
public void startSendingMessages(){
repeats = 0;
sendMessages();
}
Where when you called startSendingMessages(), the test1 would be sent, then, 5 seconds later, test2 would be sent.
The reason we are multiplying the time in seconds by 20, is because it has to be in ticks, or minecraft time, and 1 second = 20 ticks.
There's lots of other scheduler types, like SyncRepeatingTasks. To learn more about them, check out the bukkit JavaDocs: http://jd.bukkit.org/dev/apidocs/, theres also a nice tutorial from bukkit here: http://wiki.bukkit.org/Scheduler_Programming

Code not executed without a print statement [duplicate]

This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
i've been making a countdown program, and i came up with this.
package main;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Gatoo extends JFrame implements ActionListener {
private int sec, min, secTot, since = 999;
private long lastTime;
private JTextField mm = new JTextField(2), ss = new JTextField(2);
private JLabel minLab = new JLabel("Minutes:"), secLab = new JLabel(
"Seconds:");
private JButton start = new JButton("Start");
private Clip done;
private boolean started = false;
private static final long serialVersionUID = 4277921337939922028L;
public static void main(String[] args) {
Gatoo cake = new Gatoo("Title");
cake.pack();
cake.setSize(800, 600);
cake.setLocationRelativeTo(null);
cake.setDefaultCloseOperation(3);
cake.setVisible(true);
cake.run();
}
public Gatoo(String s) {
super(s);
setLayout(new FlowLayout());
start.addActionListener(this);
add(minLab);
add(mm);
add(secLab);
add(ss);
add(start);
}
#Override
public void actionPerformed(ActionEvent e) {
started = true;
}
public void play(File file) throws MalformedURLException,
UnsupportedAudioFileException, IOException,
LineUnavailableException {
AudioInputStream ais = AudioSystem.getAudioInputStream(new File(
"lib/done.wav"));
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
done = (Clip) AudioSystem.getLine(info);
done.open(ais);
done.start();
}
public void run() {
while (true) {
System.out.print("");// needed?
if (started) {
try {
min = Integer.parseInt(mm.getText());
sec = Integer.parseInt(ss.getText());
secTot = (min * 60) + sec;
lastTime = System.currentTimeMillis();
while (secTot > 0) {
since = (int) (System.currentTimeMillis() - lastTime);
if (since > 998) {
lastTime = System.currentTimeMillis();
secTot--;
}
}
play(new File("done.wav"));
} catch (NumberFormatException exception) {
System.out.println("Minutes and seconds must be numbers.");
return;
} catch (Exception exception) {
exception.printStackTrace();
}
started = false;
}
}
}
}
In the while loop at the end the countdown code doesn't execute without a print / println statement inside. How come? The program works perfectly fine with the print statement though.
First and foremost, your program is thread-unsafe because boolean started is a shared variable, but it is neither volatile nor accessed within synchronized blocks.
Now, accidentally, PrintStream#print is a synchronized method and, on any actual architecture, entering and exiting a synchronized block is implemented using memory barrier CPU instructions, which cause a complete synchronization between the thread-local state and main memory.
Therefore, by pure accident, adding the print call allows the setting of started flag by one thread (the EDT) to be visible by another (the main thread).
You have poor design for Swing application.
Don't use while(true) loop in your run() method. Read more about Concurency in Swing.
Call events with help of Listeners(ActionListener e.g.) instead of flags(started here).
Instead of counting time use Swing Timer.
Change your run() method like next:
public void run() {
min = Integer.parseInt(mm.getText());
sec = Integer.parseInt(ss.getText());
secTot = (min * 60) + sec;
Timer timer = new Timer(1000*secTot, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
play(new File("done.wav"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
timer.start();
}
actionPerformed() method :
#Override
public void actionPerformed(ActionEvent e) {
run();
}
and remove cake.run() in main method.
Look, I made a SSCCE reproducing this behavior. It is a really good question.
public class ThreadRacing implements Runnable
{
public boolean started = false;
public static void main(String[] args)
{
new ThreadRacing().test();
}
public void test()
{
new Thread(this).start();
try
{
Thread.sleep(1000);
} catch (Exception e)
{
}
started = true;
System.out.println("I did my job");
}
#Override
public void run()
{
while (true)
{
//System.out.print("");
if (started)
{
System.out.println("I started!!");
}
}
}
}
This prints: "I did my job". Nothing more. Adding a volatile keyword actually fixes the problem.
To me, it looks like the second Thread gets not notified about the update to started because he is too bussy.
I would surmise that your busy-wait loop is hogging the CPU so severely it is unable to do anything. The print statement is causing just enough of a thread context switch that it is able to get other work done.
Edit: Okay, I did a little testing. I was able to reproduce OP's problem on the HotSpot Server VM. Using Thread.currentThread().setPriority(Thread.MIN_PRIORITY); did not fix it, so it is not a starvation issue. Setting the variable to volatile as #MartinCourteau, #MarkoTopolnik suggested, did fix it. That makes sense. I couldn't originally reproduce the problem on the HotSpot Client VM; apparently its optimizations are too weak for it to cache the started variable.
(Still, if the Java audio thread had a lower than normal thread priority and it were a single-CPU system, starvation was a plausible hypothesis.)

How to pass information to a thread once it has been created

If you look at the code I have two ArrayLists that are called, pressed and released that are global. What I have to do is update those arrays with the keys that are to be pressed, then pass these updated arrays to my Thread, or update the thread.. this is the part where I'm a little lost on what I have to do.
The currently example(untested if runs), is a basic example of what I had in my actual program. When I ran it it would press the buttons once, then it would throw and error, I can't remember the error as I can't test it right now, but it had to do with the way I was using the thread.
QUESTION
How do I pass the arrays to my Thread, once the thread has been started.
Code Example:
import oscP5.OscEventListener;
import oscP5.OscMessage;
import oscP5.OscP5;
import oscP5.OscStatus;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Main implements OscEventListener {
protected BlockingQueue<Integer> _KeyQue = new ArrayBlockingQueue<>(1024);
Producer producer = new Producer(this._KeyQue);
Consumer consumer = new Consumer(this._KeyQue);
ThreadTest threadTest = new ThreadTest(this._KeyQue);
Thread prod;
Thread con;
Thread threadT;
OscP5 osc = new OscP5(this, 22556);
public static void main(String[] argv) {
Main main = new Main();
main.setup();
}
public void setup() {
prod = new Thread(producer);
con = new Thread(consumer);
threadT = new Thread(threadTest);
prod.start();
con.start();
threadT.start();
}
#Override
public void oscEvent(OscMessage theMessage) {
float val = Float.parseFloat(theMessage.arguments()[0].toString());
if (val == 1.0) {
producer.addKey(KeyEvent.VK_W);
producer.addKey(KeyEvent.VK_S);
} else {
consumer.removeKey(KeyEvent.VK_S);
}
threadTest.run();
}
#Override
public void oscStatus(OscStatus theStatus) {}
public class Producer implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public void addKey(int key) {
try {
this._KeyQue.put(key);
System.out.println("Key " + key +" added to queue");
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public Producer(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
}
}
public class Consumer implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public void removeKey(int key) {
try {
this._KeyQue.remove(key);
System.out.println("key " + key + " removed from queue");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public Consumer(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
}
}
public class ThreadTest implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public ThreadTest(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
try {
Robot robot = new Robot();
while(!this._KeyQue.isEmpty()) {
for (Integer x : this._KeyQue) {
System.out.println("Keys in que: " + x);
Thread.sleep(500);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Edit:
Ok, so I've taken a look at threads and BlockingQueue's, but the thing I still can't figure out is how to continue to run the ThreadTest's run() method without locking the program. In this example it doesn't run at all. When I directly call threadTest.run() it locks the program within it and doesn't allow for adding or removing elements.
So what I need to do is be able to run a thread in the background that is constantly running, looping through *_KeysQueue()* and, in this example, printout the number associated with the keys. This should all happen while allowing me to add and remove keys.
You can have a BlockingQueue and a method to add elements that would be called from every other thread. You can have a static method addKey that could be accessed from every other thread and that would look for adding the new key to the BlockingQueue.
You can use there the producer-consumer pattern and you can see the book Java Concurrency In Practice or the link that led me to the book, in the blog The Java Specialists. The book has examples of all queues, concurrent or synchronized lists, ways to implement code to do several things, and all without having to stop to read 50 pages about something. An example and a few paragraphs of every issue.
Have a setter method in your class
public class ThreadTest implements Runnable {
....
public void setPressedList(ArrayList<Integer> e) {
this.pressed = e;
}
public void setReleasedList(ArrayList<Integer> f)
{
this.released = f
}
}
ArrayList are not thread-safe so you should not used them this way : it could work or it could fail.
Moreover you should use some kind of synchronization mechanism instead of busy-waiting which consume resources for nothing.
So have a look at the BlockingQueue collection which will give you a simple data-passing mechanism between your threads.

Categories

Resources