I have a problem with a part of my code. My program have a thread that is getting input from the keyboard and have several threads that are waiting for that input.
The users selects first to what thread he is going to send that input. So lets says that we have 3 threads (0,1,2) plus the thread that gets the keyboard input. The user will select first what thread he wants to interact with and after that he will send the actual data to that thread.
I have a piece of code that is taking care of that process. I use ´LinkedBlockingQueue´ to achieve it.
The keyboard thread puts data in the Queue and the "workers" (the other 3 threads) get that data from that queue.
The problem is that all the threads are listening for that same Queue so I put an ID in that Queue to let the threads know if the data is directed to them or to other thread.
Here is the code:
Thread Thread_OUT = new Thread(new Runnable() {
#SuppressWarnings("unchecked")
#Override
public void run() {
while(true) {
try {
Object recibido= sharedQueue.take();
sharedQueue.put(recibido);
//System.out.println("Im the thread "+ clientID+" and I got "+recibido.toString());
if(Integer.parseInt(recibido.toString())==clientID){ // If it is for me I get the data
String x = CommandShellServer.data.get(clientID); // just get the data (it is in a hashmap)
CommandShellServer.data.clear(); // empty the hashmap
sharedQueue.clear();
OUT = do_something(x);
}
else{ // If it is not I will forward it to other thread
Thread.currentThread().wait(100);
// sharedQueue.put(recibido);
// sharedQueue.clear();
}
As you can see in the code what I do is checking if the thread that is handling the information is the one that is directed to If it is, I process it, and if it is no I put that the data again in the queue to let the other threads to check for it.
If I select the thread 0 to interact with it works. If I select others it doesn't.
Get rid of the shared queue, and let each thread have its own. Then, when you get an input, just dispatch it to the queue of appropriate thread that is intended to receive it.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Application;
import java.util.ArrayList;
import java.util.Scanner;
/**
*
* #author husseyn
*/
public class producteurConsomateur {
static Scanner clavier;
static ArrayList<String> queu;
public static void main(String[] args) {
queu=new ArrayList<>();
new Thread(){
#Override
public void run() {
clavier=new Scanner(System.in);
while (true) {
try {
sleep(1000);
} catch (Exception e) {
}
System.out.print("tape message :");
String nextLine = clavier.nextLine();
queu.add(nextLine);
// notifyAll();
}
}
}.start();
new Thread(){
#Override
public void run() {
while (true) {
try {
try {
wait();
} catch (Exception e) {
}
synchronized(this){
String get = queu.get(0);
String[] messageFormat = get.split(":");
String id=messageFormat[0];
if (id.toLowerCase().equals("id1")) {
String message=messageFormat[0];
queu.remove(0);
System.out.println("message recived to thread ID1 :"+message);
}}
} catch (Exception e) {
}
}
}
}.start();
new Thread(){
#Override
public void run() {
while (true) {
try {
try {
wait();
} catch (Exception e) {
}
synchronized(this){
String get = queu.get(0);
String[] messageFormat = get.split(":");
String id=messageFormat[0];
if (id.toLowerCase().equals("id3")) {
String message=messageFormat[0];
queu.remove(0);
System.out.println("message recived to thread ID3 :"+message);
}}
} catch (Exception e) {
}
}
}
}.start();
new Thread(){
#Override
public void run() {
while (true) {
try {
try {
wait();
} catch (Exception e) {
}
synchronized(this){
String get = queu.get(0);
String[] messageFormat = get.split(":");
String id=messageFormat[0];
if (id.toLowerCase().equals("id2")) {
String message=messageFormat[0];
queu.remove(0);
System.out.println("message recived to thread ID2 :"+message);
}}
} catch (Exception e) {
}
}
}
}.start();
}
}
And here I use a shared queue but you have to respect the message format is like id1:hello or id2:lol
Related
Consider this method from one of my handlers at server side
#Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
try {
io.netty.channel.ChannelFuture f = ctx.writeAndFlush("Executing command now...");
System.out.println("command execution future - " + f);
new Thread(new Runnable() {
int i = 4;
#Override
public void run() {
while(i >= 0 ) {
io.netty.channel.ChannelFuture f = ctx.writeAndFlush("beat till command");
System.out.println("beat till command future - " + f);
try {
Thread.sleep(6*1000);
i--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//assume some processing here
Thread.sleep(20 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
ctx.fireChannelRead(msg);
}
In above code when I write to channel in same thread it is immediately sent to the client, i.e. this message ctx.writeAndFlush("Executing command now...") is sent immediately
But when I try the same thing from a different thread, it is not sent immediately( ctx.writeAndFlush("beat till command") ). Also the future DefaultChannelPromise#5aa824c(incomplete) shows that the operation is incomplete. All these calls are deferred I guess and are completed once the main thread is done. Why is that so? Some locks on ctx?
Please tell me what am I doing wrong here?
I have rewritten this many times but I could not find a solution to this problem for a while. Some other Class writes gps.log file with lines like:
2014-09-02 10:23:13 35.185604 33.859077
2014-09-02 10:23:18 35.185620 33.859048
I am trying to read the last line of the file and update a text field in the user interface. The Thread below is overdriving the CPU into 85-100%.
I keep the file very tiny (100 lines - < 5KB). I have been working with CSV for a long time, and I think reading this file every 3 seconds should not have this footprint on the CPU. Although I have been reading huge CSV files in the past it is the first time I have this issue now that I try to update the User Interface every couple seconds. Am I doing something wrong with how I am updating the text field? Any ideas?
Thanks for looking.
new Thread(new Runnable() {
public void run() {
while (true) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
try {
try { Thread.sleep(3000); } catch (Exception e) { }
BufferedReader gpslog = new BufferedReader(new FileReader("log/gps.log"));
String line = "";
String lastLine = "";
int i=0;
while (line != null) {
i++;
lastLine = line;
line = gpslog.readLine();
}
//System.out.println(lastLine);
gpslog.close();
if (lastLine != null) { txtGPSStatus.setText(lastLine); }
//If more than 100 gps entries, flush the file
if (i>100) {
PrintWriter writer = new PrintWriter("log/gps.log");
writer.close();
}
} catch (IOException e1) {
log.error(e1);
}
}
});
}
}
}).start();
Move
try { Thread.sleep(3000); } catch (Exception e) { }
so it is just after
while(true) {
Then you will run, wait 3 secs, run, etc.
You should get a clear idea of what should be done by the background thread and what the UI thread is for!
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
public void run() {
try {
while (true) {
updateLog();
Thread.sleep(3000);
}
} catch (InterruptedException ex) {
// restore interruption flag
Thread.currentThread().interrupt();
}
}
});
private void updateLog() {
String lastLine = readLastLogLine();
Display.getDefault().syncExec(new Runnable() {
public void run() {
txtGPSStatus.setText(lastLine);
}
});
}
I am getting unexpected behavior when using console.writer() in multiple threads. In the below example, when program starts, I spawn a second thread, which is supposed to print to the console "Simulating Error." every second. Then the main thread is supposed to print to the console when you type something like "get status 9999":
public class NewConsoleExample {
private volatile boolean running=true;
private Lock lock = new ReentrantLock();
public void startService(){
Console cnsl = null;
try{
cnsl = System.console();
if (cnsl != null) {
while(running){
String input = cnsl.readLine("<console>: ");
String[] msg = input.split(" ");
if(msg.length == 3){
if(msg[0].equals("get")){
lock.lock();
cnsl.writer().println(input);
lock.unlock();
}
}
}
}
}catch(Exception ex){
ex.printStackTrace();
}
}
public void startThreadInterrupt(){
Thread consoleInterrupt = new Thread(new Runnable(){
public void run() {
Console cnsl = null;
try {
cnsl = System.console();
if (cnsl != null) {
while(running){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
cnsl.writer().println("Simulating Error.");
lock.unlock();
}
}
} catch(Exception ex){
ex.printStackTrace();
}
}
});
consoleInterrupt.start();
}
public static void main(String[] args) {
NewConsoleExample console = new NewConsoleExample();
console.startThreadInterrupt();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
console.startService();
}
}
Instead what happens is after "Simulating Error" is printed the first time, it is only ever printed again when you enter a pattern like "get status 9999". These are two entirely different threads with different behavior. Why is the other thread printing "Simulating Error" only when the main thread gets input like "get status 9999". The other thread should be printing "Simulating Error" every second regardless of what's going on in main thread.
Its cause the readLine() locks the Console object, so any other thread that tries to write on it waits for the lock to be free.
Check the docs for Console
Quote from docs:
Read and write operations are synchronized to guarantee the atomic
completion of critical operations; therefore invoking methods
readLine(), readPassword(), format(), printf() as well as the read,
format and write operations on the objects returned by reader() and
writer() may block in multithreaded scenarios.
How to pass parameter to an already running thread in java -- not in the constructor, & probably without using wait() (possible ??)
Something similar to a comment in How can I pass a parameter to a Java Thread?
Do you mean passing a parameter to an already running thread ? Because all the current answers are about passing parameters to new threads... – Valentin Rocher May 18 '09 at 10:43
[edited]
yes, I was looking for something like the producer/consumer pattern.
I wanted something like a thread in which has the processing & is ready
for keyboard input. The other thread is just to monitor network and pass
on the received text to the processing thread.
Maybe what you really need is blocking queue.When you create the thread, you pass the blocking queue in and the thread should keep checking if there is any element in the queue. Outside the thread, you can put elements to the queue while the thread is "running". Blocking queue can prevent the thread from quit if their is nothing to do.
public class Test {
public static void main(String... args) {
final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Thread running = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
String data = queue.take();
//handle the data
} catch (InterruptedException e) {
System.err.println("Error occurred:" + e);
}
}
}
});
running.start();
// Send data to the running thread
for (int i = 0; i < 10; i++) {
queue.offer("data " + i);
}
}
}
The "other thread" will have its own life, so you can't really communicate with it / pass parameters to it, unless it actively reads what you gives to it.
A thread which you allows you to communicate with it typically reads data from some buffered queue.
Have a look at ArrayBlockingQueue for instance, and read up on the Consumer-Producer pattern.
public class T1 implements Runnable {
//parameter of thread T1
public static AtomicBoolean flag = new AtomicBoolean();
#Override
public void run() {
}
}
public class T2 implements Runnable {
#Override
public void run() {
//parameter to an already running thread
T1.flag.set(true);
}
}
What about such way:
class TestRun implements Runnable
{
private int testInt = -1;
public void setInt(int i)
{
this.testInt = i;
}
#Override
public void run()
{
while (!isFinishing())
{
System.out.println("Working thread, int : " + testInt);
try
{
Thread.sleep(2500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
.....
TestRun first = new TestRun();
TestRun second = new TestRun();
(new Thread(first)).start();
(new Thread(second)).start();
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
}
first.setInt(101);
second.setInt(102);
Sorry if the question is quite simple. I am a beginner.
I have to create thread that calulates something, while the first thread works the other one have to measure if the first thread calculate the function in specified time. If not, it has to throw exception. Else it returns the answer.
I'd take the java.util.concurrent components - simple example
public void myMethod() {
// select some executor strategy
ExecutorService executor = Executors.newFixedThreadPool(1);
Future f = executor.submit(new Runnable() {
#Override
public void run() {
heresTheMethodToBeExecuted();
}
});
try {
f.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do something clever
} catch (ExecutionException e) {
// do something clever
} catch (TimeoutException e) {
// do something clever
}
}
Have your thread notify a synchronization object when it is done and have your other thread wait x number of milliseconds for it to finish.
public class Main {
private static final Object mThreadLock = new Object();
static class DoTaskThread extends Thread {
public void run() {
try {
int wait = new Random().nextInt(10000);
System.out.println("Waiting " + wait + " ms");
Thread.sleep(wait);
} catch (InterruptedException ex) {
}
synchronized (mThreadLock) {
mThreadLock.notifyAll();
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
synchronized (mThreadLock) {
DoTaskThread thread = new DoTaskThread();
thread.start();
try {
// Only wait 2 seconds for the thread to finish
mThreadLock.wait(2000);
} catch (InterruptedException ex) {
}
if (thread.isAlive()) {
throw new RuntimeException("thread took too long");
} else {
System.out.println("Thread finished in time");
}
}
}
}
join is a lot simpler than using a lock.
join (millis)
Waits at most millis milliseconds
for this thread to die. A timeout of 0
means to wait forever.
Example code:
Thread calcThread = new Thread(new Runnable(){
#Override
public void run() {
//some calculation
}
});
calcThread.start();
//wait at most 2secs for the calcThread to finish.
calcThread.join(2000);
//throw an exception if the calcThread hasn't completed.
if(calcThread.isAlive()){
throw new SomeException("calcThread is still running!");
}
Have a look at http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long,%20java.util.concurrent.TimeUnit) which allows you to handle this without dealing with thread synchronization yourself.