I am not able to update the value of a global variable in a function which is called continuously by a thread
The function code is:
public void readMessages()
{
if (srv.getServiceStatus() == Service.ServiceStatus.STARTED) {
try {
InboundMessage msg = null;
java.util.LinkedList<InboundMessage> list = new java.util.LinkedList<InboundMessage>();
srv.readMessages(list, InboundMessage.MessageClasses.UNREAD);
int checkArray = list.size();
for (int i = 0; i < list.size(); i++) {
msg = list.get(i);
System.out.println("New incoming message from: " + msg.getOriginator() +" : \t" + msg.getText() + "\n");
saveSMS(msg.getOriginator(),msg.getText());
if (checkArray == 0) {
messageArray = new String [4];
for (int j = 0 ; j<4 ; j++) {
messageArray[j] = "";
}
}
if (noOfSms < 4) {
messageArray[noOfSms] = msg.getText();
noOfSms = noOfSms + 1;
}
if (noOfSms == 3) {
Receiver r = new Receiver ();
r.Processing_ReceivedSMS(msg.getText(),msg,messageArray);
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
Here noOfSms is the global variable but its value does not change.
The function from which readMessage is called is this:
public void run(){
while (true){
readMessages();
try {
t.sleep(5000);
user_status=2;
} catch (InterruptedException e) {
System.out.println("Thread Pause Exception");
}
}
}
What's the reason behind it and what to do about it?
Since you invoke this method from thread/s there are two reasons why your variable does not get updated.
the code inside readMessages() might throw any Exception before your variable gets updated
there is a possibility that your variable never updates because it is located inside if blocks. Check the initial value of it so it can pass the if-condition
Related
I'm having a trouble passing the value of error i get when im returning the results of a table.
I have a method in my ServiceImpl class which return results for the table and also counts the amount of errors.
public List<Flow> getAllProcessContextWithCriteriaAndFlowCode(
String startDate, String endDate, String flowCode) {
List<FlowDto> flowDtos = new ArrayList<>(500);
flowDtos = processContextRepository
.fetch(startDate,
endDate, flowCode);
List<Flow> flows = new ArrayList();
// bodyguard
if (flowDtos == null || flowDtos.size() == 0) {
return flows;
}
int counter = 0;
StringBuilder idFonctionnelBuilder = new StringBuilder();
FlowDto currentFlowDto = null;
FlowState flowState = new FlowState();
FlowDto nextFlowDto = null;
Flow flowTemp = null;
Map<String, String> mapFlowIdsAndIdF = new HashMap<>();
int iNbreError = 0;
String sTempError = "";
for (int i = 0; i < flowDtos.size(); i++) {
currentFlowDto = flowDtos.get(i);
if ((i + 1) < flowDtos.size()) {
nextFlowDto = flowDtos.get(i + 1);
if (((nextFlowDto.getFlowId()
.equals(currentFlowDto.getFlowId())))) {
idFonctionnelBuilder.append(currentFlowDto.getIdf() + ", ");
continue;
} else {
flowTemp = new Flow();
flowTemp.setFlowId(currentFlowDto.getFlowId());
flowTemp.setLogRole(currentFlowDto.getLogRole());
Date date = null;
try {
date = inputFormat.parse(currentFlowDto
.getContextTime());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flowTemp.setContextTime(outputFormat.format(date));
if (currentFlowDto.getLogRole() != null) {
iNbreError++;
flowTemp.setNbreError(iNbreError);
} else {
flowTemp.setNbreError(iNbreError);
}
flowTemp.setNbreError(iNbreError);
flows.add(flowTemp);
}
} else {
flowTemp = new Flow();
if (currentFlowDto.getLogRole() != null) {
iNbreError++;
flowTemp.setNbreError(iNbreError);
} else {
flowTemp.setNbreError(iNbreError);
}
flowTemp.setContextTime(outputFormat.format(date));
flows.add(flowTemp);
}
}
LOGGER.info("[ getAllProcessContextWithCriteriaAndFlowCode ] iNbreError : "
+ iNbreError);
getNbreError(iNbreError);
return flows;
}
Then i have another method in the same class ServiceImpl who get the number of errors and set it in a variable, the result print is always the right one here.
public int getNbreError( int iNbreError){
System.out.println("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
System.out.println(iNbreError);
setCountError(iNbreError);
System.out.println("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
System.out.println(countError);
return countError;
}
What i want to do is send this value(counterror) to my RestController which is in another class called RestController so i can send it to my angular front
#GetMapping(value = "/nbreError")
public int getCountError() {
FMServiceImpl flows = new FMServiceImpl();
int countError = 0;
int iNbreError = 0;
return fmService.getNbreError( iNbreError);
}
}
Actually the result is always 0.
Thanks for your any help or advice :)
Don't use getMethod to modify data, check principle Command–query separation (CQS)
Don't create FMServiceImpl manually, Inject FMServiceImpl as dependence to your controller. in spring, Service keeps the state by default.
So I have been trying to sort this out for a couple of hours now and I'm sure its something really simple or just a simple mistake i am missing but i have a three class program, control, account and MyThreads.
Im trying to have multipule threads(cards) modify the single account, i'm trying to use a monitor so only one thread can make changes at a time, this is not what i have archived I have somehow just allowed the one thread to access the account class and no others, they seem to just disappear, i assume they are just all on wait but refuse to wake up... any help before i implode?
account code:
class account{
private static int value = 0;
private static int cards = 0;
private static int count = 0;
private static int lock = 0;
public void setValue(int temp){
value = temp;
}
public int getValue(){
// while(lock == 1){
// try{
// wait();
// }catch (InterruptedException e){
// }
// }
return value;
}
synchronized public void withdraw(int temp, String tempID){
while(lock == 1){
try{
wait();
}catch (InterruptedException e){}
}
lock=1;
value= value - temp;
count++;
System.out.println(count + "(" + tempID +")"+" "+temp+" - "+value);
lock = 0;
this.notifyAll();
}
synchronized public void deposit(int temp, String tempID){
while(lock == 1){
try{
wait();
}catch (InterruptedException e){}
}
lock=1;
value= value + temp;
count++;
System.out.println(count + "(" + tempID +")"+" - "+temp+" "+value);
lock = 0;
this.notifyAll();
}
public void setCards(int temp){
cards = temp;
}
public int getCards(){
return cards;
}
public int getCount(){
return count;
}
}
control code:
class control{
public static void main(String [] args){
account acc = new account();
acc.setValue(1000);
acc.setCards(5);
// if(args.length > 0){
// try{
// int tempCards = Integer.parseInt(args[0]);
//
// }catch (NumberFormatException e) {
// System.err.println("Number of Cards : " + args[0] + " must be an integer.");
// System.exit(1);
// }
// try{
// int tempVal = 0;
// tempVal = Integer.parseInt(args[1]);
// acc.setValue(tempVal);
// }catch (NumberFormatException e) {
// System.err.println("Account Value : " + args[1] + " must be an integer.");
// System.exit(1);
// }
// }else{
// System.err.println("No values found, please start program with the number of Cards and Bank Account Value, both in integer format");
// System.exit(1);
// }
System.out.println("Transaction Withdrawal Deposit Balance");
System.out.println(" " + acc.getValue());
for(int i=0; i<=((acc.getCards())-1); i++){
new MyThreads(Integer.toString(i+1));
}
}
}
MyThreads code:
class MyThreads implements Runnable{
private String ID;
private Thread t;
account acc = new account();
MyThreads(String tempID){
ID = tempID;
t = new Thread(this, ID);
t.start();
}
public void run(){
try{
for (int i = 0; i < 20; i++){
if(Math.random()>0.5){
int tempW = 0;
tempW = ((int)(Math.random()*100));
acc.withdraw(tempW, this.ID);
//System.out.println(acc.getCount() + "(" + this.ID +")"+" "+tempW+" -"+acc.getValue());
}else{
int tempD = 0;
tempD = ((int)(Math.random()*100));
acc.deposit(tempD, this.ID);
//System.out.println(acc.getCount() + "(" + this.ID +")"+" "+" - "+tempD+" "+acc.getValue());
}
t.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Thread " + ID + " interrupted.");
}
System.out.println("Thread " + ID + " exiting.");
}
}
I know its a mess, forgive me im lazy.
Have a look at the definition of a Monitor in Java. In your code, you use the keyword synchronized for two methods, which are the same as:
public void XX(){
lock.lock(); // lock is a private variable
try {
// code here
} finally {
lock.unlock();
}
}
In short, It is a shorthand for explicit locking and will prevent multiple threads to access the methods concurrently.
So, just remove the lock part (i.e. the while(lock==1) block) inside your synchronized methods and it will work. Also, if in other codes you need a real lock, use the Lock class, not an integer.
For more information, there are a lot of good introduction to multithreading on the web, for example this one.
Your question, and thus answer, is a wonderful mixture of static synchronized and wait-notify that's neve being called. Why use static? sounds like a magic word? skip static and make life easier.
Also note that a wait-notify is related to a specific object; if wait-notify are related to different objects they will not communicate. Have a single object that they all synchronize around.
How can I pass a parameter to a Thread?
The statement log( "before process , counter = " + i);
causes an error:
Cannot refer to a non-final variable i inside an inner class defined in a different method
Please Help
for (int i = 0; i < 20; i++) {
Thread thread = ThreadManager.createThreadForCurrentRequest(new Runnable() {
public void run() {
try {
log("before process , counter = " + i);
Thread.sleep(1000);
log("after process , " + "counter = " + i);
} catch (InterruptedException ex) {
throw new RuntimeException("Interrupted in loop:", ex);
}
}
});
thread.start();
}
As it said, just a final variable. That tells Java that it will not be changed and it can safely be used in the Runnable.
for (int i = 0; i < 20; i++) {
final int counter=i;
You need to do this:
for (int i = 0; i < 20; i++) {
final int counter = i;
// etc
}
then use counter in your thread instead of i (which, as the error message tells you, is not final, thus cannot be used in this situation).
I have done this till now
public void addStorage() {
stockStore = Storage.getLocalStorageIfSupported();
if (stockStore != null) {
stockStore.setItem(("Index" + index), ("state" + HistoryCount));
stockMap.put(("Index" + index), ("state" + HistoryCount));
}
}
public void loadStorage() {
String s;
stockStore = Storage.getLocalStorageIfSupported();
if (stockStore != null) {
stockMap = new
StorageMap(stockStore);
for (int i = 0; i < stockStore.getLength(); i++) {
if (stockMap.containsValue(index)) {
s = stockStore.getItem("Index" + index);
state = stateRecord.get(s);
clearHighlights();
setState(state);
break;
}
}
}
}
I have no idea what am I missing. These two functions are called by their handlers. Load and Save. load storage will load the stored state of chess and save will save the current chess state.
Possibly you have error here in stockMap.containsValue(index) but should be stockMap.containsValue("Index" + index), the corrected version:
for (int i = 0; i < stockStore.getLength(); i++) {
if (stockMap.containsValue("Index" + index)) {
s = stockStore.getItem("Index" + index);
state = stateRecord.get(s);
clearHighlights();
setState(state);
break;
}
}
During execution the method is called and the integer i displays as 0 on screen. However, no output is forthcoming from inside the for loop, suggesting the for loop doesnt execute. I have also tested this with breakpoints, and have obtained the same results. Any help is appreciated.
private void decrypt_btnActionPerformed(java.awt.event.ActionEvent evt) {
int ciphertext_length = Ciphertext().length();
String decrypted_char = "";
int i = 0;
System.out.println("increment" + i);
try {
for (i = 0; i == ciphertext_length; i++) {
System.out.println("test" + i);
String cipher_current_char = getLetterAtIndex(Ciphertext(), i);
int pos_char_in_alphabet = getIndexAtLetter(Alphabet(), cipher_current_char);
decrypted_char = decrypted_char +
getLetterAtIndex(Alphabet(), pos_char_in_alphabet - 5);
status_label.setText(100 / i + "%");
}
} catch (Exception e) {
e.getMessage();
}
plain_ta.setText(decrypted_char);
}
for (i = 0; i==ciphertext_length; i++){
should in all likelihood be
for (i = 0; i<ciphertext_length; i++){