I'm writing a small function that will update my ProgressBar and a JLabel base on weighted random integers. The thread is sleeping correctly and the random values are coming through, however, my progress bar and jlabel are not updating.
It is also leaving my GUI unresponsive. It isn't locking my GUI completely (I'm able to click buttons, but it doesn't execute the functions associated with those buttons).
Throwing a print statement in the run() method is not printed out. So I'm thinking it never gets in there.
Here is my method so far:
private void updateProgressBar(int max) {
final int maxDiamonds = max;
int i = 0;
while(i <= max) {
//get random obstacle found
final Obstacle o = obstacle.next();
System.out.println("Obstacle: " + o.getName());
//get random number of diamonds for obstacle
int numDiamonds = Integer.parseInt(numFoundDiamonds.next());
System.out.println("Number of Diamonds: " + numDiamonds);
//set currentValue for the progress bar
final int currentValue = i;
for(int j = o.getRemovalTime(); j >= 0; j--) {
final int rSecs = j;
System.out.println("Time remaining to remove: " + rSecs);
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setString(currentValue + "/" + maxDiamonds);
statusLabel.setText("Found " + o.getName() + ". Removing: " + rSecs + " s Remaining.");
}
});
java.lang.Thread.sleep(1000);
} catch (InterruptedException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
}
}
i += numDiamonds;
}
}
Perhaps I'm overlooking something simple.
I can also provide more code regarding the other classes used, but I feel that the issue lies in the code provided.
You're calling Thread.sleep(...) on the Swing event thread which will put the whole Swing thread and application to sleep. Use a background thread such as with a SwingWorker.
Related
my exercise is composed of an SharedResource with an array, a NumberGenerator Class and a SumClass.
2 Threads of NumberGenerator and 2 Threads of SumClass.
I have to insert numbers in the array from the SharedResource with both threads of NumberGenerator Class.
This part is done correctly.
My problem is in the run method of the NumberGenerator Class.
These Threads must read alternatively the index of the array, the first thread, lets call it H1, read the index 0-2-4-6... even index, the another one, H2, odd index... But when 1 thread is running the other must wait.
So the output should be something like this:
Array:[10,35,24,18]
Thread name: H1 - Number:10
Thread name: H2 - Number:35
Thread name: H1 - Number:24
Thread name: H2 - Number:18
My problem resides in the notify and wait methods. When I call the wait method, it automatically stop both Threads even when a notifyAll is present.
I need to just use 1 method, I cant use a evenPrint method and an OddPrint method for example.
Code of my class:
public class SumatoriaThread extends Thread{
String name;
NumerosCompartidos compartidos; // Object that contains the array.
double sumatoria; //Parameter used to sum all the numbers
static int pos = 0; // pos of the object
static int threadOrder = 0; //just a way to set the order of the Threads.
int priority; //Value of the priority
public SumatoriaThread(NumerosCompartidos compartidos, String name){
this.name = name;
this.compartidos = compartidos;
sumatoria = 0;
priority = threadOrder;
threadOrder++;
System.out.println("Hilo " + this.name + " creado.");
}
public void run() {
//Array Length
int length = this.compartidos.length();
int i = 0;
while (pos < length) {
//Don't actually know if this is correct.
synchronized (this) {
//Just to be sure that the first Thread run before the second one.
if (priority == 1) {
try {
priority = 0;
//Call a wait method until the next notify runs.
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(SumatoriaThread.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
//Even numbers
if (pos % 2 == 0) {
System.out.println("Nombre Thead: " + Thread.currentThread().getName() + " valor numero: " + this.compartidos.getValor(pos));
pos++;
//To activate the Thread which is waiting.
this.notifyAll();
try {
//Then I set to wait this one.
this.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
System.out.println("Nombre Thead: " + Thread.currentThread().getName() + " valor numero: " + this.compartidos.getValor(pos + 1));
pos++;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(SumatoriaThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
}
}
I wrote a small program for testing java's Thread.
The problem is that I cannot get results as I predicted: 100 records every time.
I got random number of records. and after I remove the comment of this line:
//System.out.println(name + " Completed.");
I got 100 records as predicted every time.
In other words, I add a System.out.println(), everything works perfect.
Is that the java's bug or something I didn't noticed?
MyThread.java
public class MyThread extends Thread {
#Override
public void run() {
String name = Thread.currentThread().getName();
for (int i = 1; i <= 10; i++) {
if (i == 10) {
//System.out.println(name + " Completed.");
TestThread.al.add(name);
}
}
}
}
TestThread.java
import java.util.ArrayList;
public class TestThread {
public static ArrayList<String> al = new ArrayList<String>();
public static void main(String[] args) throws Exception {
ArrayList<MyThread> mt = new ArrayList<MyThread>();
//set
for (int i = 0; i < 100; i++) {
mt.add(new MyThread());
mt.get(i).setName("Worker " + (i + 1));
}
//start
for (int i = 0; i < 100; i++) {
mt.get(i).start();
}
//end
for (int i = 0; i < 100; i++) {
mt.get(i).join();
}
//result
for (int i = 0; i < al.size(); i++) {
System.out.println("Rank " + (i+1) + " : " + al.get(i));
}
}
}
the ArrayList is not thread-safe, maybe there exist a case: the two threads write data to the same positon of the arrayList ,you can use Vector instead for it is thread-safe.
for more information about thread-safe come here
cainiaofei has answered it, but wanted to add few more points:
Your ArrayList object al is causing the problem as it is being accessed(reads/writes) by many threads concurrently.
You need to know the below basic points:
Whenever many threads concurrently access an object ensure that you need to use thread-safe classes like Collections.synchronizedList() (prefer this) or Vector.
If you need thread safety for primitive types, you can make use of JDK's atomic package, for which you can look here.
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 have the following code to find the sum of natural numbers from 1 to 5000. It's a simple exercise to practice concurrency.
public static void main(String[] args) throws InterruptedException {
final int[] threadNb = new int[] {5};
final Integer[] result = new Integer[1];
result[0] = 0;
List<Thread> threads = new LinkedList<>();
IntStream.range(0, threadNb[0]).forEach(e -> {
threads.add(new Thread(() -> {
int sum = 0;
int idx = e * 1000 + 1;
while (!Thread.interrupted()) {
if (idx <= (e + 1) * 1000) {
sum += idx++;
} else {
synchronized(result) {
result[0] += sum;
System.err.println("sum found (job " + e + "); sum=" + sum + "; result[0]=" + result[0] + "; idx=" + idx);
Thread.currentThread().interrupt();
}
}
}
synchronized(result) {
System.err.println("Job " + e + " done. threadNb = " + threadNb[0]);
threadNb[0]--;
System.err.println("threadNb = " + threadNb[0]);
}
}));
});
threads.forEach(Thread::start);
//noinspection StatementWithEmptyBody
while(threadNb[0] > 0);
System.out.println("begin result");
System.out.println(result[0]);
System.out.println("end result");
}
Sometimes, when I run the code, the last 3 System.out.println() are not displayed. If I put a statement in the while(threadNb[0] > 0), like another System.out.println(), my problem never happen again.
Can anyone explain me this behaviour?
Thanks in advance for any help
Nothing about how the threadNb variable is declared tells the JVM that it needs to make updates to it visible to other threads. At what point updates to your variable become visible to other threads is entirely up to the JVM implementation, it can make them visible or not depending on circumstances. Also, the JIT is free to re-order or optimize away code if it thinks it can get away with it, and it bases its decisions on the visibility rules. So it's hard to say exactly what happens here because the behavior is left unspecified by the Java language specs, but definitely you're having a problem where your worker threads' updates are usually not getting seen by the main thread.
If you replace the arrays with AtomicInteger then the updates are guaranteed to become visible to other threads. (Volatile works too, but AtomicInteger is preferred. In order to use volatile you have to make the variable an instance or class member.) If you save the updated values in a local variable then you don't need synchronization:
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.atomic.*;
public class SumNumbers {
public static void main(String[] args) throws InterruptedException {
AtomicInteger threadNb = new AtomicInteger(5);
AtomicInteger result = new AtomicInteger(0);
List<Thread> threads = new LinkedList<>();
IntStream.range(0, threadNb.intValue()).forEach(e -> {
threads.add(new Thread(() -> {
int sum = 0;
int idx = e * 1000 + 1;
while (!Thread.currentThread().isInterrupted()) {
if (idx <= (e + 1) * 1000) {
sum += idx++;
} else {
int r = result.addAndGet(sum);
System.out.println("sum found (job " + e + "); sum="
+ sum + "; result=" + r
+ "; idx=" + idx);
Thread.currentThread().interrupt();
}
}
System.out.println("Job " + e + " done.");
int threadNbVal = threadNb.decrementAndGet();
System.out.println("Job " + e + " done, threadNb = " + threadNbVal);
}));
});
threads.forEach(Thread::start);
//noinspection StatementWithEmptyBody
while(threadNb.intValue() > 0);
System.out.println("result=" + result.intValue());
}
}
where you can see the updates become visible.
Busy waiting is not preferred since it wastes CPU cycles. You do see it in lock-free programming, but it is not a good thing here. Thread#join will work or you can use a CountdownLatch.
Be aware that using Thread#interrupted() clears the interrupted flag. Usually it's used when you're about to throw InterruptedException, otherwise it's better to use Thread.currentThread().isInterrupted(). It doesn't hurt anything in this specific case because the while loop test is the only thing using the flag, so whether it gets cleared is irrelevant.
The most likely explanation is that the compiler optimizes your code so that the value of threadNb[0] is cached. Therefore, the main thread may not see updates done by other threads. Making your counter volatile can help to solve this problem.
However, the current approach with a busy wait is generally not the best solution. You should use the join() method of the class Thread to let your main thread wait till each of them has ended.
For example:
for(Thread t: threads) {
try{
t.join();
} catch(InterruptedException e) {}
}
So the assignment is the following fictional story:
For Nelson Mandela's funeral, people could pay their last respects to him at a building.
Because a lot of people wanted to do this, everything needs to be planned right. The people who will have access are his ex-guards (in my code it's called 'Bewaker', pardon the Dutch), civilian ('Burger') and several 'Dignitaries'.
Guards will have access all the time to enter the building
Dignitaries have priority above 'Burgers' (civilians). Because of security measures no dignitaries may enter if there are civilians inside. When one or more Dignitaries are entering the queue no new 'Burgers' may enter the building and every waiting Dignitary are allowed access when the last civilian has left the building.
Dignitaries may enter any time there are other Dignitaries inside and no waiting civilians outside.
To prevent civilians will have a chance to pay their last respects as well, as soon as a civilian has entered the queue a maximum of 5 Dignitaries may enter the building. After which 100 civilians may enter the building and will have priority above Dignitaries.
'Burgers' may always enter when there are no Dignitaries waiting or inside.
I have the following code, but I keep getting stuck after a few rotations and it enters a deadlock, or it just doesn't work properly. Edit: The problem is the following:
After a few runs the consecutiveDignitary counter doesnt reset and no new people waiting in line will enter the building because a deadlock has occured somewhere, but I don't see where. The output indicates that all civilians and all dignitaries are waiting in line, no-one can enter the building, and the consecutiveDignitary counter doesnt reset.
Your input is greatly appreciated! (Pardon the occasional Dutch words)
package main;
import bezoeker.Bewaker;
import bezoeker.Burger;
import bezoeker.Dignitary;
import monitor.*;
public class Apl {
private final static int NR_OF_DIG = 25; //DIG = hoogwaardigheidbekleder
private final static int NR_OF_CIV = 150; //CIV = burger
private final static int NR_OF_BEW = 20; //BEW = bewaker
/**
* #param args
*/
public static void main(String[] args) {
MonitorAlt m = new MonitorAlt();
//Monitor monitor = new Monitor();
//creation of new entities
Thread [] dig; //dignitary
Thread [] bur; //burger
Thread [] bew; //bewaker
dig = new Thread[NR_OF_DIG];
bur = new Thread[NR_OF_CIV];
bew = new Thread[NR_OF_BEW];
//start all the threads
for (int i = 0 ; i < NR_OF_DIG ; i++) {
dig[i] = new Dignitary("dig"+i, m);
dig[i].start();
assert (dig[i].isAlive());
}
for (int j = 0 ; j < NR_OF_CIV ; j++) {
bur[j] = new Burger("bur"+j, m);
bur[j].start();
assert (bur[j].isAlive());
}
for (int k = 0 ; k < NR_OF_BEW ; k++) {
bew[k] = new Bewaker("bew"+k, m);
bew[k].start();
assert (bew[k].isAlive());
}
}
}
Monitor class:
package monitor;
import java.util.concurrent.locks.*;
import bezoeker.*;
public class MonitorAlt {
public Lock lock; //locking critical sections
private Condition civilianLine; //condition denouncing the civilians waiting in the line
private Condition dignitaryLine;//condition denouncing the dignitaries waiting in the line
private Condition bothEntry; //condition denouncing wether >...???
private int nrOfCiviliansInLine, nrOfCiviliansInside,
nrOfDignitariesInLine, nrOfDignitariesInside,
consecutiveDignitary;
private int civCounter;
private boolean dignitaryEntered;
public MonitorAlt() {
lock = new ReentrantLock();
civilianLine = lock.newCondition();
dignitaryLine = lock.newCondition();
bothEntry = lock.newCondition();
dignitaryEntered = false;
}
public void enterBuilding(VisitorType vt) throws InterruptedException {
lock.lock();
switch (vt) {
case BURGER:
//check wether a civilian is allowed to go inside
System.out.println(((Burger) Thread.currentThread()).getName() + " joined the line");
nrOfCiviliansInLine++;
while (burgerNotAllowed()) {
bothEntry.await();
}
while (buildingFull()) {
civilianLine.await();
}
//after a civilian is allowed inside, go inside
System.out.println(((Burger) Thread.currentThread()).getName() + " entered the building.");
nrOfCiviliansInside++;
nrOfCiviliansInLine--;
break;
case BEWAKER:
System.out.println(((Bewaker) Thread.currentThread()).getName() + " entered the building.");
break;
case DIGNITARY:
System.out.println(((Dignitary) Thread.currentThread()).getName() + " joined the line");
nrOfDignitariesInLine++;
while (dignitaryNotAllowed()) {
dignitaryLine.await();
}
if (nrOfCiviliansInLine > 0) {
consecutiveDignitary++;
}
//after a dignitary is allowed inside, go inside
System.out.println(((Dignitary) Thread.currentThread()).getName() + " entered the building.");
nrOfDignitariesInLine--;
nrOfDignitariesInside++;
if (consecutiveDignitary == 5 && nrOfCiviliansInLine == 0) {
consecutiveDignitary = 0;
}
civilianLine.signal();
break;
}
lock.unlock();
}
public void leaveBuilding(VisitorType vt) {
lock.lock();
switch (vt) {
case BURGER:
System.out.println(((Burger) Thread.currentThread()).getName() + " left the building");
nrOfCiviliansInside--;
dignitaryLine.signalAll();
print();
break;
case BEWAKER:
System.out.println(((Bewaker) Thread.currentThread()).getName() + " left the building");
break;
case DIGNITARY:
System.out.println(((Dignitary) Thread.currentThread()).getName() + " left the building");
nrOfDignitariesInside--;
if (consecutiveDignitary >= 5 && nrOfCiviliansInLine > 0 && nrOfDignitariesInside == 0) {
civilianLine.signalAll();
}
dignitaryLine.signalAll();
print();
break;
}
lock.unlock();
}
public boolean dignitaryNotAllowed() {
return (nrOfCiviliansInside > 0 || (consecutiveDignitary >= 5 && nrOfCiviliansInLine > 0));
}
public boolean burgerNotAllowed() {
return ((consecutiveDignitary < 5 && nrOfDignitariesInside > 0) || (nrOfDignitariesInLine > 0 && nrOfCiviliansInside > 0));
}
public boolean buildingFull() {
dignitaryEntered();
return (dignitaryEntered || (nrOfDignitariesInside > 0 && consecutiveDignitary < 5));
}
public void dignitaryEntered() {
if (nrOfDignitariesInside > 0) {
dignitaryEntered = true;
} else {
dignitaryEntered = false;
}
}
public void print() {
System.out.println("------");
System.out.println("# civ in line: \t" + nrOfCiviliansInLine );
System.out.println("# civ inside: \t" + nrOfCiviliansInside );
System.out.println("# dig in line: \t" + nrOfDignitariesInLine );
System.out.println("# dig inside: \t" + nrOfDignitariesInside );
System.out.println("# consecutive dig: \t" + consecutiveDignitary );
System.out.println("------");
}
public void resetCivCounter() {
civCounter = 0;
}
public void resetConsecutiveDignitary() {
consecutiveDignitary = 0;
}
}
VisitorType is an Enum Class, very basic.
The classes 'Bewaker' (guard), 'Burger' (civilian) and Dignitary are all pretty similar, so here's the class Dignitary:
package bezoeker;
import monitor.*;
public class Dignitary extends Thread {
private Monitor monitor;
private MonitorAlt m;
public Dignitary(String name, Monitor monitor) {
super(name);
this.monitor = monitor;
}
public Dignitary(String name, MonitorAlt m) {
super(name);
this.m = m;
}
public void run() {
while (true) {
try {
justLive();
m.enterBuilding(VisitorType.DIGNITARY);
payLastRespects();
m.leaveBuilding(VisitorType.DIGNITARY);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void justLive() {
try {
System.out.println("Dignitary " + getName() + " just living.");
Thread.sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void payLastRespects() throws InterruptedException {
Thread.sleep((int) (Math.random() * 2000));
assert ((Thread.currentThread()).isInterrupted());
System.out.println(Thread.currentThread().getName() + " paid his last respects.");
}
}
Any help/suggestions is welcome.
Marvin
I didn't actually run the code and I'm not very familiar with Java thread locking. But looking over it, it looks like these lines will cause a dead lock:
bothEntry.await();
civilianLine.await();
dignitaryLine.await();
Scenario:
5 Bewaker's enter the building.
5 Bewaker's pays respects.
Dignitary thread activates and enters the building.
lock.lock() is called.
Dignitary cannot enter, and so calls dignitaryLine.await().
Bewaker thread reactivates and tries to leave the building.
Deadlock, dignitary is holding onto the lock, but bewaker needs the lock to alert the dignitary that they can enter.
I hope that helps. :)
EDIT Generally, never perform any sleeping or waiting while you are holding a lock. As for a solution, the best thing (and I believe common practice) to do with threading and locking is to only lock on the smallest unit of work possible. Rather than locking on a full method (actually two full methods), you should identify what you want to control in series, and only lock on that.
Fitting into what you have, you could setup a second lock which is used for leaving the room, this would allow people to leave even though people were waiting to enter. You would need to change your int's to AtomicInteger's for the numbers to work as expected. However I wouldn't recommend this, multiple locks tend to allow even more complicated bugs to appear, also this method doesn't respect your priority ordering requirement.
If I was going to do this, I would more accurately model the relationship between the outside world and the room. Specifically I would add a queue into which people were placed before being allowed into the room. I would split your MonitorAlt class into a Room and a Queue (probably using a java.util.PriorityQueue which would handle most of the priority work for you). People are put into the queue if the room is full, and the room pulls people from the queue when there is space available inside.
I have a console application in which I would like to put a non-deterministic progress bar on the command line while some heavy computations are done. Currently I simply print out a '.' for each iteration in a while loop similar to the following:
while (continueWork){
doLotsOfWork();
System.out.print('.');
}
which works but I was wondering if anyone had a better/cleverer idea since this can get to be a little bit annoying if there are many iterations through the loop.
Here an example to show a rotating progress bar and the traditional style :
import java.io.*;
public class ConsoleProgressBar {
public static void main(String[] argv) throws Exception{
System.out.println("Rotating progress bar");
ProgressBarRotating pb1 = new ProgressBarRotating();
pb1.start();
int j = 0;
for (int x =0 ; x < 2000 ; x++){
// do some activities
FileWriter fw = new FileWriter("c:/temp/x.out", true);
fw.write(j++);
fw.close();
}
pb1.showProgress = false;
System.out.println("\nDone " + j);
System.out.println("Traditional progress bar");
ProgressBarTraditional pb2 = new ProgressBarTraditional();
pb2.start();
j = 0;
for (int x =0 ; x < 2000 ; x++){
// do some activities
FileWriter fw = new FileWriter("c:/temp/x.out", true);
fw.write(j++);
fw.close();
}
pb2.showProgress = false;
System.out.println("\nDone " + j);
}
}
class ProgressBarRotating extends Thread {
boolean showProgress = true;
public void run() {
String anim= "|/-\\";
int x = 0;
while (showProgress) {
System.out.print("\r Processing " + anim.charAt(x++ % anim.length()));
try { Thread.sleep(100); }
catch (Exception e) {};
}
}
}
class ProgressBarTraditional extends Thread {
boolean showProgress = true;
public void run() {
String anim = "=====================";
int x = 0;
while (showProgress) {
System.out.print("\r Processing "
+ anim.substring(0, x++ % anim.length())
+ " ");
try { Thread.sleep(100); }
catch (Exception e) {};
}
}
}
Try using a carriage return, \r.
In GUI applications the approach is generally a spinning circle or bouncing/cycling progress bar. I remember many console applications using slashes, pipe and hyphen to create a spinning animation:
\ | / -
You could also use a bouncing character in brackets:
[-----*-----]
Of course, as the other answered mentioned, you want to use return to return to the start of the line, then print the progress, overwriting the existing output.
Edit: Many cooler options mentioned by Will in the comments:
Cooler ASCII Spinners?
If you know how much work you have to do and how much is left (or done), you might consider printing out a percent complete bar graph sort of progress bar. Depending on the scope of this project, this could simply be in ascii or you could also consider using graphics.