I've got thread class which increments lable value from 0 to n. Thread code:
public class
SimpleThread implements Runnable {
Thread t;
volatile boolean stop = true;
int n;
JLabel label;
String name;
SimpleThread(String name) {
this.name = name;
t = new Thread(this, "settingThread");
t.start();
}
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
}
}
public void start(int n, JLabel label) {
stop = false;
this.n = n;
this.label = label;
}
}
Thread must work until stop value isn't true. Also I've got 2 thread objects st1 and st2 with different arguments:
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
So first thread should increment timeLabel1 from 0 to 10 and st2 - from 0 to 5. And now the question. How can I make my programm wait until threads has passed the stage in the cycle? I mean something like this:
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
//stage
}
}
And then:
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
//wait until both stages aren't done
System.out.println("yep");
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: Администратор
* Date: 22.11.13
* Time: 21:17
* To change this template use File | Settings | File Templates.
*/
public class StackOverflow implements ActionListener {
JButton button = new JButton("Button");
SimpleThread st1 = new SimpleThread("1st"), st2 = new SimpleThread("2nd");
JLabel timeLabel1 = new JLabel("0"), timeLabel2 = new JLabel("0");
StackOverflow() {
JFrame jfrm = new JFrame("Strategy fighting");
jfrm.setLayout(new FlowLayout());
jfrm.setSize(300, 150);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.addActionListener(this);
jfrm.add(button);
jfrm.add(timeLabel1);
jfrm.add(timeLabel2);
jfrm.setVisible(true);
}
public class SimpleThread implements Runnable {
Thread t;
volatile boolean stop = true;
int n;
JLabel label;
String name;
SimpleThread(String name) {
this.name = name;
t = new Thread(this, "settingThread");
t.start();
}
public void run() {
while (true) {
while (stop) {
}
System.out.println(name + " stop:" + stop);
for (int i = 0; i < n; i++) {
label.setText(String.valueOf(i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
stop = true;
}
}
public void start(int n, JLabel label) {
stop = false;
this.n = n;
this.label = label;
}
}
public void actionPerformed(ActionEvent e) {
st1.start(10, timeLabel1);
st2.start(5, timeLabel2);
System.out.println("yep");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new StackOverflow();
}
});
}
}
Your question already has the answer: the Phaser class. ;)
Something like this should do the trick:
static final Phaser phaser = new Phaser(NUM_THREADS + 1); // +1 for the main thread
In your threads:
run() {
// do stage 1
phaser.arriveAndAwaitAdvance(); // wait until everyone is done with stage 1
// do stage 2
}
And in your main:
startThreads(NUM_THREADS);
phaser.arriveAndAwaitAdvance(); // wait until stage 1 is done
// ... do something else
Related
I have 3 threads
1st printing A
2nd printing B
3rd printing C
I want to print in sequence A B C A B C A B C and so on.....
So I wrote the program below, but I am not able to achieve the same.
I am aware of the problem that when status=1 at that time say for example B1 and C1 thread are waiting and when I do notifyAll() both waiting thread wake up and depending on CPU allocation it might print B or C.
in this case I want only B to be printed after A.
what modification I need to do.
public class NotifyAllExample {
int status=1;
public static void main(String[] args) {
NotifyAllExample notifyAllExample = new NotifyAllExample();
A1 a=new A1(notifyAllExample);
B1 b=new B1(notifyAllExample);
C1 c=new C1(notifyAllExample);
a.start();
b.start();
c.start();
}
}
class A1 extends Thread{
NotifyAllExample notifyAllExample;
A1(NotifyAllExample notifyAllExample){
this.notifyAllExample = notifyAllExample;
}
#Override
public void run() {
try{
synchronized (notifyAllExample) {
for (int i = 0; i < 100; i++) {
if(notifyAllExample.status!=1){
notifyAllExample.wait();
}
System.out.print("A ");
notifyAllExample.status = 2;
notifyAllExample.notifyAll();
}
}
}catch (Exception e) {
System.out.println("Exception 1 :"+e.getMessage());
}
}
}
class B1 extends Thread{
NotifyAllExample notifyAllExample;
B1(NotifyAllExample notifyAllExample){
this.notifyAllExample = notifyAllExample;
}
#Override
public void run() {
try{
synchronized (notifyAllExample) {
for (int i = 0; i < 100; i++) {
if(notifyAllExample.status!=2){
notifyAllExample.wait();
}
System.out.print("B ");
notifyAllExample.status = 3;
notifyAllExample.notifyAll();
}
}
}catch (Exception e) {
System.out.println("Exception 2 :"+e.getMessage());
}
}
}
class C1 extends Thread{
NotifyAllExample notifyAllExample;
C1(NotifyAllExample notifyAllExample){
this.notifyAllExample = notifyAllExample;
}
#Override
public void run() {
try{
synchronized (notifyAllExample) {
for (int i = 0; i < 100; i++) {
if(notifyAllExample.status!=3){
notifyAllExample.wait();
}
System.out.print("C ");
notifyAllExample.status = 1;
notifyAllExample.notifyAll();
}
}
}catch (Exception e) {
System.out.println("Exception 3 :"+e.getMessage());
}
}
}
Convert those IF statements to WHILE statements to get the desired behavior:
if (notifyAllExample.status != 2){
notifyAllExample.wait();
}
to
while (notifyAllExample.status != 2){
notifyAllExample.wait();
}
This will ensure that if a thread is notified, it won't go out of the while loop until the status value is what it expects.
Also, mark status as volatile so that the threads won't have a local copy.
public class RunThreadsInOrder implements Runnable {
static int numThread = 1;
static int threadAllowedToRun = 1;
int myThreadID;
private static Object myLock = new Object();
public RunThreadsInOrder() {
this.myThreadID = numThread++;
System.out.println("Thread ID:" + myThreadID);
}
#Override
public void run() {
synchronized (myLock) {
while (myThreadID != threadAllowedToRun) {
try {
myLock.wait();
} catch (InterruptedException e) {
} catch (Exception e) {}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("myThreadID is running: " + myThreadID);
myLock.notifyAll();
threadAllowedToRun++;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1 = new Thread(new RunThreadsInOrder());
Thread t2 = new Thread(new RunThreadsInOrder());
Thread t3 = new Thread(new RunThreadsInOrder());
Thread t4 = new Thread(new RunThreadsInOrder());
Thread t5 = new Thread(new RunThreadsInOrder());
Thread t6 = new Thread(new RunThreadsInOrder());
Thread t7 = new Thread(new RunThreadsInOrder());
t7.start();
t6.start();
t5.start();
t4.start();
t3.start();
t2.start();
t1.start();
}
}
public class Main {
public static void main(String[] args) throws IOException{
Thread t1 = new Thread(new A(), "1");
Thread t2 = new Thread(new A(), "2");
Thread t3 = new Thread(new A(), "3");
t1.start();
try{
t1.join();
}catch (Exception e){
}
t2.start();
try{
t2.join();
}catch (Exception e){
}
t3.start();
try{
t3.join();
}catch (Exception e){
}
}
}
class A implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName());
}
}
or you can use Executor Framework
public class Sequence {
int valve = 1;
public static void main(String[] args){
Sequence s = new Sequence();
ExecutorService es = Executors.newFixedThreadPool(3);
List<Runnable> rList = new ArrayList<>();
rList.add(new A(s));
rList.add(new B(s));
rList.add(new C(s));
for(int i = 0; i < rList.size(); i++){
es.submit(rList.get(i));
}
es.shutdown();
}
}
class A implements Runnable{
Sequence s;
A(Sequence s){
this.s = s;
}
public void run(){
synchronized (s) {
for (int i = 0; i < 10; i++) {
while (s.valve != 1) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
s.valve = 2;
s.notifyAll();
}
}
}
}
class B implements Runnable{
Sequence s;
B(Sequence s){
this.s = s;
}
public void run() {
synchronized (s) {
for (int i = 0; i < 10; i++) {
while (s.valve != 2) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
s.valve = 3;
s.notifyAll();
}
}
}
}
class C implements Runnable{
Sequence s;
C(Sequence s){
this.s = s;
}
public void run() {
synchronized (s) {
for(int i = 0; i < 10; i++) {
while (s.valve != 3) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
s.valve = 1;
s.notifyAll();
}
}
}
}
In the first case the join for each thread causes the threads to wait for one another. In the second case a list stores the threads and executor executes them one after another creating 3 threads
Another way to do this is where only one runnable class is present and communication between thread is done via static variable in the main class and a variable in the runnable class
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Seq {
int i = 1;
public static void main(String[] args){
Seq s = new Seq();
Common c1 = new Common(s, 1);
Common c2 = new Common(s, 2);
Common c3 = new Common(s, 3);
List<Runnable> l = new ArrayList<>();
l.add(c1);
l.add(c2);
l.add(c3);
ExecutorService es = Executors.newFixedThreadPool(3);
for(int i = 0; i < 3; i++){
es.submit(l.get(i));
}
es.shutdown();
}
}
class Common implements Runnable{
Seq s;
int o;
Common(Seq s, int o){
this.s = s;
this.o = o;
}
public void run(){
synchronized (s) {
for (int z = 0; z < 100; z++) {
if(s.i > 3)
s.i = 1;
while (s.i != o) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(o);
s.i++;
s.notifyAll();
}
}
}
}
I was asked to write a similar program in an interview with the added condition that it should be extensible in a way that we can provide our own count of threads and they should print characters with the first thread printing 'A' and then the subsequent threads printing B, C, D and so on. Here's how I did it.
public class AlternateCharPrinter {
public static char ch = 65;
private static void createAndStartThreads(int count) {
Object lock = new Object();
for (int i = 0; i < count; i++) {
new Thread(new AlternateCharRunner((char) (65 + i), lock)).start();
}
}
public static void main(String[] args) {
createAndStartThreads(4);
}
}
class AlternateCharRunner implements Runnable {
private char ch;
private Object lock;
private static int runnerCount;
public AlternateCharRunner(char ch, Object lock) {
this.ch = ch;
this.lock = lock;
runnerCount++;
}
#Override
public void run() {
while (true) {
synchronized (lock) {
while (ch != AlternateCharPrinter.ch) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(AlternateCharPrinter.ch++);
if (AlternateCharPrinter.ch == (65 + runnerCount)) {
AlternateCharPrinter.ch = 65;
}
lock.notifyAll();
}
}
}
}
You need to replace
if (notifyAllExample.status!=1)
with
while (notifyAllExample.status!=1)
and same thing in the other 2 classes. If not, then as soon as the wait exits the thread continues without knowing if it is its turn.
Replace:
if(notifyAllExample.status!=1){
notifyAllExample.wait();
}
with:
while(notifyAllExample.status!=1){
notifyAllExample.wait();
}
in all classes accordingly.
The simplest solution to solve this can be following way:
public class PrintInOrder implements Runnable {
private int valueToPrint;
private int id;
private static int turn = 1;
private static int RESET_TURN_THRESHOLD = 3;
public PrintInOrder() {
this.valueToPrint = -1;
}
public PrintInOrder(int id, int val) {
this.id = id;
this.valueToPrint = val;
}
#Override
public void run() {
while(true) {
if (turn == this.id) {
System.out.println(Thread.currentThread().getName() + "::::" + valueToPrint);
turn++;
}
if (turn > RESET_TURN_THRESHOLD) {
turn = 1;
}
}
}
public static void main(String []args) {
Thread t1 = new Thread(new PrintInOrder(1, 1));
t1.setName("THREAD-1");
t1.start();
Thread t2 = new Thread(new PrintInOrder(2, 2));
t2.setName("THREAD-2");
t2.start();
Thread t3 = new Thread(new PrintInOrder(3, 3));
t3.setName("THREAD-3");
t3.start();
}
}
/*
OUTPUT::::
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
...
*/
Here is my solution -
I have created three threads each thread knows what it needs to print and what comes after it.
I have also created a Class NLock which holds the next word which needs to be printed.
Whenever a thread is able to acquire NLock lock then it checks
if it's his turn if yes then it prints the word and set the next value to be printed in NLock or else it waits till it's his turn
public class SynchronizeThreeThreads {
public static void main(String args[]) throws InterruptedException {
NLock lock=new NLock("A");
Thread a =new Thread(new PrintInOrder("A","B",lock));
Thread b =new Thread(new PrintInOrder("B","C",lock));
Thread c =new Thread(new PrintInOrder("C","A",lock));
a.start();
b.start();
c.start();
c.join(); // Once all is done main thread will exit
System.out.println("Done");
}
}
class NLock{
private String value;
public NLock(String value) {
this.value=value;
}
public String getValue() {
return value;
}
public void setValue(String next) {
this.value=next;
}
}
class PrintInOrder implements Runnable{
private String word;
private String next;
private NLock lock;
public PrintInOrder(String word, String next,NLock lock){
this.word=word;
this.next=next;
this.lock=lock;
}
#Override
public void run() {
int i=0;
while(i<3) {
synchronized (lock) {
try {
//Check if it's my turn
if(lock.getValue().equals(word)) {
System.out.println(this.word);
//Set what next needs to be printed
//So that when that thread wakes up it knows that it's his turn
lock.setValue(next);
i++;
lock.notifyAll();
Thread.sleep(100);
}
else //Nope not my turn wait
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Below is the output
A
B
C
A
B
C
A
B
C
Done
This is my attempt to solve the same. Any suggestions are welcome. This is the complete running code.
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
#Slf4j
public class SeqExecution {
static class SeqThread extends Thread {
private static final Object lock = new Object();
private static final AtomicInteger AUTO_COUNTER = new AtomicInteger();
private static final TrackExecution trackExecution = new TrackExecution();
private final int seqNo;
SeqThread(Runnable runnable) {
super(runnable);
this.seqNo = AUTO_COUNTER.getAndIncrement();
}
#SneakyThrows
#Override
public void run() {
while (true) {
synchronized (lock) {
while (trackExecution.CUR_EXECUTION.get() != this.seqNo) {
try {
lock.wait(100);
} catch (Exception e) {}
}
//log.info("Thread: {} is running", this.seqNo);
super.run();
sleep(1000);
trackExecution.increment();
lock.notifyAll();
}
}
}
static class TrackExecution {
private final AtomicInteger CUR_EXECUTION = new AtomicInteger();
int get() {
return CUR_EXECUTION.get();
}
synchronized void increment() {
var val = CUR_EXECUTION.incrementAndGet();
if (val >= SeqThread.AUTO_COUNTER.get()) {
CUR_EXECUTION.set(0);
}
}
}
}
public static void main(String[] args) {
final var seqThreads = List.of(new SeqThread(() -> System.out.print("A ")),
new SeqThread(() -> System.out.print("B ")),
new SeqThread(() -> System.out.print("C ")));
seqThreads.forEach(Thread::start);
seqThreads.forEach(t -> {
try {
t.join();
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
});
}
}
I think it's simpler to achieve this using join.
Example:
public static void main(String[] args) {
final Thread t1 = new Thread("t1") {
#Override
public void run() {
System.out.println("i am thread: " + Thread.currentThread().getName());
}
};
final Thread t2 = new Thread(t1, "t2") {
#Override
public void run() {
t1.start();
try {
t1.join();
} catch ( InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("i am thread: " + Thread.currentThread().getName());
}
};
Thread t3 = new Thread(t2, "t3") {
#Override
public void run() {
t2.start();
try {
t2.join();
} catch ( InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("i am thread: " + Thread.currentThread().getName());
}
};
t3.start();
}
Here is my solution please try and let me know
package thread;
class SyncPrinter {
public static void main(String[] args) {
SyncPrinterAction printAction1 = new SyncPrinterAction(new int[]{1,5,9,13}, true);
SyncPrinterAction printAction2 = new SyncPrinterAction(new int[]{2,6,10,14}, true);
SyncPrinterAction printAction3 = new SyncPrinterAction(new int[]{3,7,11,15}, true);
SyncPrinterAction printAction4 = new SyncPrinterAction(new int[]{4,8,12,16}, false);
printAction1.setDependentAction(printAction4);
printAction2.setDependentAction(printAction1);
printAction3.setDependentAction(printAction2);
printAction4.setDependentAction(printAction3);
new Thread(printAction1, "T1").start();;
new Thread(printAction2, "T2").start();
new Thread(printAction3, "T3").start();
new Thread(printAction4, "T4").start();
}
}
class SyncPrinterAction implements Runnable {
private volatile boolean dependent;
private SyncPrinterAction dependentAction;
int[] data;
public void setDependentAction(SyncPrinterAction dependentAction){
this.dependentAction = dependentAction;
}
public SyncPrinterAction( int[] data, boolean dependent) {
this.data = data;
this.dependent = dependent;
}
public SyncPrinterAction( int[] data, SyncPrinterAction dependentAction, boolean dependent) {
this.dependentAction = dependentAction;
this.data = data;
this.dependent = dependent;
}
#Override
public void run() {
synchronized (this) {
for (int value : data) {
try {
while(dependentAction.isDependent())
//System.out.println("\t\t"+Thread.currentThread().getName() + " :: Waithing for dependent action to complete");
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
dependentAction.setDependent(true);
System.out.println(Thread.currentThread().getName() + " :: " +value);
dependent = false;
}
}
}
private void setDependent(boolean dependent) {
this.dependent = dependent;
}
private boolean isDependent() {
return dependent;
}
}
I have a program that estimates the value of PI every million trials. However, I want the program to be paused when I click on pause and to resumes when I click on run, using wait() and notify().
I must use multiple threads as well as a Boolean as a signal of where should it pause and run, but I do not know how. I am confused.
Any ideas?
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Ex03 extends JFrame implements Runnable, ActionListener {
int n = 0;
int c = 0;
double Pi;
int change = 1000000;
boolean runing = true;
JLabel actualpi = new JLabel("The Actual value of PI " + Math.PI);
JLabel estimation = new JLabel("Current Estimate: ");
JLabel tri = new JLabel("Number Of Trials: " + n);
JButton run = new JButton("Run");
JButton pause = new JButton("Pause");
public Ex03() {
super("Ex 03");
setLayout(new GridLayout(4, 1));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
add(actualpi);
add(estimation);
add(tri);
add(run);
run.addActionListener(this);
pause.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
Thread thread = new Thread(this);
if (e.getSource() == run) {
thread.start();
remove(run);
add(pause);
} else if (e.getSource() == pause) {
remove(pause);
add(run);
try {
thread.wait();
} catch (InterruptedException e1) {
}
}
}
public void run() {
n++;
while (runing) {
double x = Math.random();
double y = Math.random();
if (((x * x) + (y * y)) <= 1)
c++;
n++;
Pi = (4.0 * (double) c / n);
if (n == change) {
estimation.setText("Current Estimate: " + Pi);
tri.setText("Number Of Trials: " + n);
change = change + 1000000;
}
try {
Thread.sleep(0);
} catch (InterruptedException e) {
}
}
}
public static void main(String[] args) {
new Ex03();
}
}
Here is example how to do it in console application using Semaphore:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws Exception {
PiThread piThread = new PiThread();
piThread.start();
BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
String cmd;
while ((cmd = bufferRead.readLine()) != null) {
System.out.println("write p to pause, r to resume, s to stop");
switch (cmd) {
case "p":
piThread.pauseComputation();
break;
case "r":
piThread.resumeComputation();
break;
case "s":
piThread.stopComputation();
piThread.join();
return;
}
}
}
public static class PiThread extends Thread {
private volatile boolean stop = false;
private volatile int total = 0;
private volatile int insideCircle = 0;
private Semaphore semaphore = new Semaphore(1, true);
#Override
public void run() {
while (!stop) {
for (int i = 0; i < 1000; i++) {
double x = Math.random();
double y = Math.random();
if (((x * x) + (y * y)) <= 1)
insideCircle++;
total++;
}
// using semaphores is slow
try {
// not to garbage stdout
Thread.sleep(100);
semaphore.acquire();
semaphore.release();
}
catch (InterruptedException e) {
// exit
return;
}
System.out.println("pi: " + getPiApproximation());
System.out.flush();
}
}
public void pauseComputation() {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void resumeComputation() {
semaphore.release();
}
public void stopComputation() {
stop = true;
}
public double getPiApproximation() {
return 4*(double)insideCircle / (double)total;
}
}
}
It may not be the best way to handle this in GUI but will give you a good start. The main idea is to use Semaphore to block worker thread. For this to work you must always call pauseComputation before resumeComputation otherwise there will be deadlock. After you call stopComputation you cannot resumeComputation or pauseComputation.
I'm writing a program that constantly pings a server. I wrote the code to check it once and put the ping in a JLabel and put it in a method called setPing().
Here is my code
private void formWindowOpened(java.awt.event.WindowEvent evt) {
setPing();
}
That worked but only did it once, so I did:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
for(;;){
setPing();
}
}
But this doesn't even work for the first time.
I didnt put the setPing method because it was too long so here it is:
public String setPing(){
Runtime runtime = Runtime.getRuntime();
try{
Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
int i = 0;
i = line.indexOf("Average");
if(i > 0){
String finalPing = "";
line.toCharArray();
try
{
finalPing = "";
for(int x = i; x < i + 17; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException e)
{
try
{
finalPing = "";
for(int x = i; x < i + 16; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException f)
{
try
{
finalPing = "";
for(int x = i; x < i + 15; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException g){}
}
}
String final1Ping = finalPing.replaceAll("[^0-9]", "");
return final1Ping;
}
}
}catch(IOException e){
}
return "";
}
UPDATE
Just in case this is important, Im using netbeans. I created a form and put this code in the formWindowOpened evt instead of calling it in main:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(1000, timerListener);
timer.start();
jLabel1.setText(label.getText());
timer.stop();
// TODO add your handling code here:
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime("lol.garena.com");
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public JComponent getUI() {
return label;
}
public static int pingTime(String hostnameOrIP) {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
Use a Swing Timer for repeating tasks & a SwingWorker for long running tasks. E.G. of both below - it uses a Timer to repeatedly perform a 'long running' task (a ping) in a SwingWorker.
See Concurrency in Swing for more details on the Event Dispatch Thread and doing long running or repeating tasks in a GUI.
This code combines a long running task ('pinging' a server) using SwingWorker invoked from a repeating task (updating the JLabel repeatedly with the times) using a Swing based Timer.
import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;
public class LabelUpdateUsingTimer {
static String hostnameOrIP = "stackoverflow.com";
int delay = 5000;
JLabel label = new JLabel("0000");
LabelUpdateUsingTimer() {
label.setFont(label.getFont().deriveFont(120f));
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(delay, timerListener);
timer.start();
JOptionPane.showMessageDialog(
null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
timer.stop();
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime();
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public static int pingTime() {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (Exception weTried) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception weTried) {}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new LabelUpdateUsingTimer();
}
};
SwingUtilities.invokeLater(r);
}
}
You could use a Thread. The problem is you are blocking the main thread, thereby blocking your program. To get around this, start a background Thread to update components repeatedly.
(Note: you need to update GUI components on the EDT, so use SwingUtilities.invokeLater)
(new Thread((new Runnable(){
#Override
public void run(){
while(true){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
refToJLabel.setText(Math.random());
}
});
}
}
}))).start();
I'm writing a program that constantly pings a server. I wrote the code to check it once and put the ping in a JLabel and put it in a method called setPing().
Here is my code
private void formWindowOpened(java.awt.event.WindowEvent evt) {
setPing();
}
That worked but only did it once, so I did:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
for(;;){
setPing();
}
}
But this doesn't even work for the first time.
I didnt put the setPing method because it was too long so here it is:
public String setPing(){
Runtime runtime = Runtime.getRuntime();
try{
Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
int i = 0;
i = line.indexOf("Average");
if(i > 0){
String finalPing = "";
line.toCharArray();
try
{
finalPing = "";
for(int x = i; x < i + 17; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException e)
{
try
{
finalPing = "";
for(int x = i; x < i + 16; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException f)
{
try
{
finalPing = "";
for(int x = i; x < i + 15; x++)
{
finalPing = finalPing + (line.charAt(x));
}
}catch(IndexOutOfBoundsException g){}
}
}
String final1Ping = finalPing.replaceAll("[^0-9]", "");
return final1Ping;
}
}
}catch(IOException e){
}
return "";
}
UPDATE
Just in case this is important, Im using netbeans. I created a form and put this code in the formWindowOpened evt instead of calling it in main:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(1000, timerListener);
timer.start();
jLabel1.setText(label.getText());
timer.stop();
// TODO add your handling code here:
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime("lol.garena.com");
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public JComponent getUI() {
return label;
}
public static int pingTime(String hostnameOrIP) {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
Use a Swing Timer for repeating tasks & a SwingWorker for long running tasks. E.G. of both below - it uses a Timer to repeatedly perform a 'long running' task (a ping) in a SwingWorker.
See Concurrency in Swing for more details on the Event Dispatch Thread and doing long running or repeating tasks in a GUI.
This code combines a long running task ('pinging' a server) using SwingWorker invoked from a repeating task (updating the JLabel repeatedly with the times) using a Swing based Timer.
import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;
public class LabelUpdateUsingTimer {
static String hostnameOrIP = "stackoverflow.com";
int delay = 5000;
JLabel label = new JLabel("0000");
LabelUpdateUsingTimer() {
label.setFont(label.getFont().deriveFont(120f));
ActionListener timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new PingWorker().execute();
}
};
Timer timer = new Timer(delay, timerListener);
timer.start();
JOptionPane.showMessageDialog(
null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
timer.stop();
}
class PingWorker extends SwingWorker {
int time;
#Override
protected Object doInBackground() throws Exception {
time = pingTime();
return new Integer(time);
}
#Override
protected void done() {
label.setText("" + time);
}
};
public static int pingTime() {
Socket socket = null;
long start = System.currentTimeMillis();
try {
socket = new Socket(hostnameOrIP, 80);
} catch (Exception weTried) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception weTried) {}
}
}
long end = System.currentTimeMillis();
return (int) (end - start);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new LabelUpdateUsingTimer();
}
};
SwingUtilities.invokeLater(r);
}
}
You could use a Thread. The problem is you are blocking the main thread, thereby blocking your program. To get around this, start a background Thread to update components repeatedly.
(Note: you need to update GUI components on the EDT, so use SwingUtilities.invokeLater)
(new Thread((new Runnable(){
#Override
public void run(){
while(true){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
refToJLabel.setText(Math.random());
}
});
}
}
}))).start();
I expected to see close to 200,000 lines (196,608) of output from the loop in this code. It only prints one line. Can anyone spot the blunder?
import java.awt.*;
import java.util.*;
import javax.swing.*;
class SwingWorkerUnicodeTest {
private String[] fontNameArray;
private JLabel output = new JLabel("Processing..");
private JProgressBar progressBar = new JProgressBar();
class CodePointDetailWorker extends SwingWorker<Object, Object> {
private ArrayList<Character.UnicodeBlock> unicodeBlockNames;
private ArrayList<Character.UnicodeScript> unicodeScripts;
private int[] glyphCount = new int[fontNameArray.length];
public CodePointDetailWorker() {
progressBar.setVisible(true);
Arrays.fill(glyphCount, 0);
}
#Override
protected Void doInBackground() throws Exception {
// Check for for the first 3 planes. The next 11 are unassigned
int pS = 3*65536;
for (int kk = 0; kk < pS; kk++) {
System.out.println("doInBackground " + kk + " " + pS);
doForEveryCodePoint(kk);
}
return null;
}
#Override
public void done() {
output.setText("Done!");
}
private final void doForEveryCodePoint(final int codePoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint);
if (block != null && !unicodeBlockNames.contains(block)) {
unicodeBlockNames.add(block);
}
Character.UnicodeScript us = Character.UnicodeScript.of(codePoint);
if (us == null || us.toString() == null) {
} else {
if (!unicodeScripts.contains(us)) {
unicodeScripts.add(us);
}
}
// fonts - test for points in all 6 defined blocks.
for (int ii = 0; ii < fontNameArray.length; ii++) {
Font f = new Font(fontNameArray[ii], Font.PLAIN, 16);
if (f.canDisplay(codePoint)) {
glyphCount[ii]++;
}
}
}
}
public SwingWorkerUnicodeTest() {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
fontNameArray = ge.getAvailableFontFamilyNames();
JPanel gui = new JPanel(new BorderLayout());
gui.add(progressBar, BorderLayout.CENTER);
gui.add(output, BorderLayout.PAGE_END);
CodePointDetailWorker cpdw = new CodePointDetailWorker();
cpdw.execute();
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new SwingWorkerUnicodeTest();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
Edit
Fixed code, based on the advice of the first 2 answers.
It now both implements the overridden method that reports errors, but initializes the arrays for ..much output and shows progress in the progress bar.
import java.awt.*;
import java.util.*;
import javax.swing.*;
class SwingWorkerUnicodeTest {
private JLabel output = new JLabel("Processing..");
// Check for for the first 3 planes. The next 11 are unassigned
int pS = 3 * 65536;
private JProgressBar progressBar = new JProgressBar(0, pS);
class CodePointDetailWorker extends SwingWorker<Object, Object> {
private ArrayList<Character.UnicodeBlock> unicodeBlockNames;
private ArrayList<Character.UnicodeScript> unicodeScripts;
private int[] glyphCount;
private String[] fontNameArray;
public CodePointDetailWorker(String[] fontNameArray) {
this.fontNameArray = fontNameArray;
progressBar.setVisible(true);
glyphCount = new int[fontNameArray.length];
Arrays.fill(glyphCount, 0);
unicodeBlockNames = new ArrayList<Character.UnicodeBlock>();
unicodeScripts = new ArrayList<Character.UnicodeScript>();
}
#Override
protected Void doInBackground() throws Exception {
for (int kk = 0; kk < pS; kk++) {
if (kk % 500 == 0) {
progressBar.setValue(kk);
}
doForEveryCodePoint(kk);
}
progressBar.setValue(0);
return null;
}
#Override
public void done() {
try {
get();
output.setText("Done!");
} catch (Exception ex) {
ex.printStackTrace();
output.setText("Bad: " + ex.getMessage());
}
}
private final void doForEveryCodePoint(final int codePoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codePoint);
if (block != null && !unicodeBlockNames.contains(block)) {
unicodeBlockNames.add(block);
}
Character.UnicodeScript us = Character.UnicodeScript.of(codePoint);
if (us == null || us.toString() == null) {
} else {
if (!unicodeScripts.contains(us)) {
unicodeScripts.add(us);
}
}
// fonts - test for points in all 6 defined blocks.
for (int ii = 0; ii < fontNameArray.length; ii++) {
Font f = new Font(fontNameArray[ii], Font.PLAIN, 16);
if (f.canDisplay(codePoint)) {
glyphCount[ii]++;
}
}
}
}
public SwingWorkerUnicodeTest(String[] names) {
JPanel gui = new JPanel(new BorderLayout());
gui.add(progressBar, BorderLayout.CENTER);
gui.add(output, BorderLayout.PAGE_END);
CodePointDetailWorker cpdw = new CodePointDetailWorker(names);
cpdw.execute();
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
new SwingWorkerUnicodeTest(fontNames);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
There is, likely, an Exception being thrown within the doInBackground method, which is, obviously, causing it to exit.
In your done method, even if it returns nothing, you should call get to ensure that nothing went wrong during the execution of the doInBackground method
#Override
public void done() {
try {
get();
output.setText("Done!");
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
output.setText("Bad: " + ex.getMessage());
}
}
You're not initializing your ArrayLists
public CodePointDetailWorker() {
unicodeBlockNames = new ArrayList<>();
unicodeScripts = new ArrayList<>();
...
}
so a NPE is silently being thrown in the SwingWorker once this statement is encountered
if (block != null && !unicodeBlockNames.contains(block)) {
^---null