I'm trying to write a library for my users, and would like it to be as easy to use as possible. Right now, to use it, you have to start a new thread, and set a lot of variables to track, in your main class, however my users are not always experienced in Java, and threading might be too hard for some of my users.
So I want to move the entire threading into my class, and allow users to call a function, to start the thread.
Here is the thread I'm currently running in the main class:
int valueToAdd = 0;
DreamStatsTracker tracker = new DreamStatsTracker();
StartSessionResponse response = tracker.StartSession("ae-13s-90-11", "Abe");
System.out.println(response.getMessage());
System.out.println("Adding skill Herblore");
String message = tracker.AddSkill(response.getSessionId(), Skill.HERBLORE, "Abe");
Thread thread = new Thread(() -> {
while(true) {
tracker.SetValueForSkill(response.getSessionId(), Skill.HERBLORE, valueToAdd);
}
});
I would like to move that entire thing into the DreamStatsTracker class, and do something like this from the main class:
DreamStatsTracker tracker = new DreamStatsTracker();
tracker.AddSkill(Skill1, ValueForSkill1);
tracker.AddSkill(Skill2, ValueForSkill2);
tracker.Start();
This would start a new instance of the DreamStatsTracker, which would start a new thread, and track the values of the added skills continuously in the background, while the main class is running.
How would I approach this, and is it even possible?
I finally solved my issue, by hours of testing and trying.
This is what I did:
Tracker class:
Thread mainThread;
public DreamStatsTracker(){
mainThread = new Thread(() -> {
while(true){
for (SkillAndValue skillAndValue : Skills) {
try {
SetValueForSkill(this.SessionId, skillAndValue.getSkill(), skillAndValue.getValue());
System.out.println("Added value: " + skillAndValue.getValue());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(2000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public void AddSkillAndValue(Skill Skill, Callable<Integer> function) throws Exception{
Skills.add(new SkillAndValue(Skill, function));
}
public void Start(){
for (SkillAndValue skillAndValue : Skills) {
AddSkill(this.SessionId, skillAndValue.getSkill(), this.Username);
}
this.mainThread.start();
}
This is the main class:
public static void main(String[] args) throws Exception {
DreamStatsTracker tracker = new DreamStatsTracker();
tracker.StartNewSession("ae-13s-90-11", "Abe");
tracker.AddSkillAndValue(Skill.HERBLORE, getRandomNumber());
tracker.Start();
}
private static Callable<Integer> getRandomNumber(){
return new Callable<Integer>(){
public Integer call(){
Random random = new Random();
return random.nextInt(10000);
}
};
}
Related
I have an object A on which I'm updating some data every second and other objects B and C which want to use the data only once per update.
Every object work in parallel.
How can I make B and C wait for the update in A ?
I've seen some similar questions but their responses didn't help me.
I've seen that I could use a "synchronized" bloc on an object D, but they just put the bloc without telling how to instanciate or share that object.
The following code is what I use for my tests. I managed to get them working in parallel but I'm stuck with the suspending part.
This is the class for A
public class Master{
public static void main(String[] args) throws Exception {
Worker B = new Worker("B");
B.start();
Worker C = new Worker("C");
C.start();
while(true)
{
Thread.sleep(1000);
// update data
// notify every thread waiting that they can resume
}
}
}
This is the class used for B and C
public class Worker extends Thread
{
Worker(String name)
{
super("Worker " + name);
}
public void run()
{
int i = 0;
while(!this.isInterrupted())
{
// wait for A to update data
System.out.println(i);
i++;
}
System.out.println("thread interrupted");
}
}
From there, what do I need to add for the purpose I'm looking for ?
To do it very low level, only using the lang APIs, you should use wait/notifyAll.
Not that I used Main.class as an arbitrary object to synchronize
public class Main {
public static void main(String[] args) {
SharedData sharedData = new SharedData();
Worker w1 = new Worker("Worker 1", sharedData);
Worker w2 = new Worker("Worker 2", sharedData);
w1.start();
w2.start();
while (true) {
try {
Thread.sleep(1000);
sharedData.increase();;
System.out.println("Master: " + sharedData.value());
synchronized (Main.class) {
Main.class.notifyAll();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class SharedData {
private int data = 0;
public void increase () {
data++;
}
public int value() {
return data;
}
}
class Worker extends Thread {
private String workerName;
private SharedData sharedData;
public Worker(String workerName, SharedData sharedData) {
super();
this.workerName = workerName;
this.sharedData = sharedData;
}
#Override
public void run() {
while (true) {
try {
synchronized (Main.class) {
Main.class.wait();
}
System.out.println(workerName + ": " + sharedData.value());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Not sure if I understand you correctly, but this might be worth checking out for you:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
Why use threads at all? Why not just do this?
public class Master {
public static void main(String[] args) {
Worker B = new Worker("B");
Worker C = new Worker("C");
while(true) {
Thread.sleep(1000);
updateData();
B.doWork();
C.doWork();
}
}
}
public class Worker
{
public void doWork() {
System.out.println(i);
i++;
}
private int i = 0;
}
I have a piece of Java program that essentially does the following:
public static void main(String[] args)
{
while(true)
{
// does stuff ...
}
}
The infinite loop is there by design - when left alone the program will loop infinitely. For the most part it works fine. However, sometimes I want to take the program down for maintenance, and when I take it down I want to make sure that it runs through all the code in the loop to the end then exit.
I am wondering what is the best solution for this. One idea I have in mind is to do something like this:
public static void main(String[] args)
{
File f = new File("C:\exit.txt");
while(!f.exists())
{
// does stuff ...
}
}
which basically allows me to gracefully get out of the loop by creating a file called "exit.txt". This is probably OK for my purposes, but I would like to know if there are better, alternative methods.
I think that the WatchService that was introduced in Java 7 may be of use here (if you prefer a file based approach that is). From the JavaDocs:
A watch service that watches registered objects for changes and events. For example a file manager may use a watch service to monitor a directory for changes so that it can update its display of the list of files when files are created or deleted.
Basically what this means is that you can set up a WatchService that can watch a folder for changes. When a change occurs you can choose what actions to take.
The following code uses the WatchService to monitor a specified folder for changes. When a change has happened it executes a Runnable that the caller has provided (the method runWhenItIsTimeToExit).
public class ExitChecker {
private final Path dir;
private final Executor executor;
private final WatchService watcher;
// Create the checker using the provided path but with some defaults for
// executor and watch service
public ExitChecker(final Path dir) throws IOException {
this(dir, FileSystems.getDefault().newWatchService(), Executors.newFixedThreadPool(1));
}
// Create the checker using the provided path, watcher and executor
public ExitChecker(final Path dir, final WatchService watcher, final Executor executor) {
this.dir = dir;
this.watcher = watcher;
this.executor = executor;
}
// Wait for the folder to be modified, then invoke the provided runnable
public void runWhenItIsTimeToExit(final Runnable action) throws IOException {
// Listen on events in the provided folder
dir.register(watcher,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
// Run it async, otherwise the caller thread will be blocked
CompletableFuture.runAsync(() -> {
try {
watcher.take();
} catch (InterruptedException e) {
// Ok, we got interrupted
}
}, executor).thenRunAsync(action);
}
}
So, how do we use the checker then? Well, the following code illustrates this:
public static void main(String... args) throws IOException, InterruptedException {
// Setup dirs in the home folder
final Path directory = Files.createDirectories(
new File(System.getProperty("user.home") + "/.exittst").toPath());
// In this case we use an AtomicBoolean to hold the "exit-status"
AtomicBoolean shouldExit = new AtomicBoolean(false);
// Start the exit checker, provide a Runnable that will be executed
// when it is time to exit the program
new ExitChecker(directory).runWhenItIsTimeToExit(() -> {
// This is where your exit code will end up. In this case we
// simply change the value of the AtomicBoolean
shouldExit.set(true);
});
// Start processing
while (!shouldExit.get()) {
System.out.println("Do something in loop");
Thread.sleep(1000);
}
System.out.println("Exiting");
}
Finally, how do you exit the program then? Well simply touch a file in the specified folder. Example:
cd ~/.exittst
touch exit-now.please
Resources:
A good tutorial on how to use the WatchService
WatchService JavaDocs
A good article about CompletableFuture
More stuff about CompletableFuture
Why the WatchService is slow on Mac OS X
One could employ some sophisticated techniques here. The file watchdog is one option. RMI could be another. But in fact, the mechanisms that are required here are quite simple, so I'd like to propose another (very simple) solution.
Note: This solution is just one option, showing that it is possible to do it that way. It is not a general recommendation, and whether it is "good" or not depends on the application case.
The solution is simply based on Sockets. The ServerSocket#accept method already encapsulates the functionality that you want:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
Based on this, it is trivial to create such a "remote control": The server just waits for a connection, and sets a flag when the connection is opened:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;
class RemoteExitServer
{
private final AtomicBoolean flag = new AtomicBoolean();
RemoteExitServer()
{
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
waitForConnection();
}
});
t.setDaemon(true);
t.start();
}
private void waitForConnection()
{
ServerSocket server = null;
Socket socket = null;
try
{
server = new ServerSocket(1234);
socket = server.accept();
flag.set(true);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (server != null)
{
try
{
server.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
boolean shouldExit()
{
return flag.get();
}
}
The client does exactly that: It opens a connection, and nothing else
import java.io.IOException;
import java.net.Socket;
public class RemoteExitClient
{
public static void main(String[] args)
{
Socket socket = null;
try
{
socket = new Socket("localhost", 1234);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
The application is then also very simple:
public class RemoteExitTest
{
public static void main(String[] args)
{
RemoteExitServer e = new RemoteExitServer();
while (!e.shouldExit())
{
System.out.println("Working...");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
System.out.println("done");
}
}
(The code could be made even more concise with try-with-resources, but this should not matter here)
You could make use of runtime shutdown hook. That way you won't need to use console input in order to stop the loop. If JVM is being closed normally then shutdown hook thread will run. This thread will wait for the end of current loop iteration. Keep in mind that there are some limitations when using hooks though: https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#addShutdownHook-java.lang.Thread-
import java.util.concurrent.CountDownLatch;
public class Test {
private volatile static CountDownLatch lastIterationLatch = null;
private static boolean stop = false;
public static void main(String [] args) throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
lastIterationLatch = new CountDownLatch(1);
try {
lastIterationLatch.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
while(!stop) {
System.out.println("iteration start");
Thread.sleep(200);
System.out.println("processing...");
Thread.sleep(200);
System.out.println("processing...");
Thread.sleep(200);
System.out.println("processing...");
Thread.sleep(200);
System.out.println("iteration end");
if(lastIterationLatch != null) {
stop = true;
lastIterationLatch.countDown();
}
}
}
}
For something quick/dirty, use Signals:
boolean done = false;
// ...
Signal.handle(new Signal("USR1"), new SignalHandler() {
#Override
public void handle(Signal signal) {
// signal triggered ...
done = true;
}
});
// ...
while(!done) { ... }
Then, use kill -USR1 _pid_ to trigger the signal.
You could use a AtomicBoolean as in the test program below.
To suspend just type true into the console to resume type false. The program will never exit.
public class Test2 {
public static void main(String[] args) {
final AtomicBoolean suspended = new AtomicBoolean(false);
new Thread() {
public void run() {
while (true)
{
Scanner sc = new Scanner(System.in);
boolean b = sc.nextBoolean();
suspended.set(b);
}
}
}.start();
while(true){
if(!suspended.get()){
System.out.println("working");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
//System.exit(0) //if you want to exit rather than suspend uncomment.
}
}
}
}
I am writing code that communicates on serially with several machines. Each machine interacts with an instance of a communicator class and that class has a serial port event listener.
When the machine recieves enough data it peforms a test that is quadratic. (cant be helped as the test itself is quadratic) and the input can be large. As a result I am afraid that some of the serial events wont be registered if the code is doing the calculation.
As a solution I considered creating a Thread that runs the calculation and setting it to sleep during its loop for a time determined by the number of machines connected. However I then thought that maybe it would be a better idea if I could put that Thread asleep from the serialevent method? is this possible or will the thread not run until the method that is running finishes?
Now in the code below I have included the Thread.sleep within the Calculations method as this is what I was going to do if the serialevent cant interupt the thread
private class CalculationThread implements Runnable{
#Override
public void run()
{
calculateResult();
}
}}
private void calculateResult() {
ArrayList<Double> theoretical_vals;
ArrayList<ArrayList<Double>> theoretical_curves = new ArrayList();
double current_maxdiff, maxdiff;
double ao = measurements.get(0).getMeasurement();
theoretical_vals = RadioCalculations.theoreticalVals(measurements, hf, ao);
theoretical_curves.add(theoretical_vals);
int index = 1;
for (MeasurePoint m : measurements) {
theoretical_vals = RadioCalculations.calibratecontrolValues(measurements, index, hf);
try {
Thread.sleep(20*(parent.getNumberOfTests()-1));}
catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
theoretical_curves.add(theoretical_vals);
index++;
}
index = 1;
maxdiff = 0;
for (ArrayList a : theoretical_curves) {
try {
Thread.sleep(20*(parent.getNumberOfTests()-1));
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
current_maxdiff = compareValues(a, measurements);
if (current_maxdiff > maxdiff) {
if (current_maxdiff > pass_limit) {
passed = false;
failed_measurementpoint = index;
break;
}
maxdiff = current_maxdiff;
index++;
}
}
passed = true;
max_dev = maxdiff;
logResults();
}
public void serialEvent(SerialPortEvent spe) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
pauseListen(false);
if (spe.getEventType()== SerialPortEvent.DATA_AVAILABLE){
try {
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);}}
catch (IOException e) {e.printStackTrace();}
input_line= new String(readBuffer,0,numBytes);
input_line = input_line.replaceAll("[\n\r]","*");
buffer.append(input_line);
if (input_line.contains("*")){
input_line= buffer.toString();
input_line = input_line.replaceAll("[*]","");
buffer.setLength(0);
pauseListen(true);
update(input_line);}}
}
}
You could use a BlockingQueue (since Java 5) for put the new calculations in this queue while there is one calculation in process.
First, you need a wrapper class for you received data of the serial port:
class CalculationWrapper {
// fields
// getters setters
public void calculateResult() {
// operations
}
}
The method calculateResult for do the calculations can be in this class or in the next class:
class Calculator implements Runnable {
private final BlockingQueue<CalculationWrapper> queue;
Calculator(BlockingQueue<CalculationWrapper> q) {
queue = q;
}
public void run() {
try {
while (true) {
CalculationWrapper wrapper = queue.take();
wrapper.calculateResult();
}
} catch (InterruptedException ex) {
// log error
}
}
}
The method take wait until there is more new calculations in the queue.
The class for the listener of events of serial port (and for put the new calculations) could be:
class Receiver implements Runnable, SerialPortEventListener {
private final BlockingQueue<CalculationWrapper> queue;
Receiver(BlockingQueue q) {
queue = q;
}
public void run() {
try {
while (true) {
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
// log
}
}
public void serialEvent(SerialPortEvent evt) {
switch (evt.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
try {
// read
CalculationWrapper wrapper = new CalculationWrapper();
// set data on wrapper
queue.put(wrapper);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
And the setup class o main class:
class Setup {
public static void main(String args[]) {
// get port
// register listener
BlockingQueue q = new ArrayBlockingQueue(10);
Receiver p = new Receiver(q);
Calculator c1 = new Calculator(q);
new Thread(p).start();
new Thread(c1).start();
}
}
This in one way. See more:
Lesson: Concurrency (The Java Tutorials > Essential Classes)
SerialPort example « javax.comm « Java by API
The Java Communications API: A Working Example - By Rick Proctor
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);
I'm using java. I'm trying to execute a thread, but the issue I'm getting is
thread.start() method is getting executed, but as we know when we call the start method of thread, the run() method gets called internally.
But in my case the run() method is not getting executed:
public static void main(String[] args) throws Exception {
parseArguments(args);
ScraperStore scraperStore = ScraperStore.getInstance();
SocialSiteManager siteManager = new SocialSiteManager();
sitesToScrape = siteManager.getSocialSitesToScrape();
for (SocialSite site : sitesToScrape) {
ScrapeThread srThread = new ScrapeThread("srThread");
Thread scraper = new Thread(srThread);
srThread.setSiteToScrape(site);
srThread.setPageTypeToScrape(startPageToScrape);
srThread.setTypeToScrape(typeToScrape);
ArrayList<String> listOfValues = ScraperStore.getNextUrlToScrape(startPageToScrape, site);
srThread.setTypeToScrape(typeToScrape);
try {
srThread.setUrlOwnedBy(listOfValues.get(0));
srThread.setStartUrl(listOfValues.get(1));
scraper.start();
boolean state = scraper.isAlive();
scrapeThreads.add(scraper);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Thread class:
class ScrapeThread {
public ScrapeThread(String threadName) {
thread = new Thread(this,threadName);
System.out.println(thread.getName());
}
}
Run method:
public void run() {
try {
System.out.println("in the run method");
selenium = new DefaultSelenium(config.getHost(), Integer.parseInt(config.getPort()),
config.getBrowser(), config.getUrl());
selenium.start();
Integer count = 0;
while (startUrl != null) {
HtmlPage homePage = new HtmlPage();
homePage.setCreatedBy(new String());
homePage.setCreatedon(new String());
homePage.setModifiedBy(new String());
homePage.setModifiedOn(new String());
homePage.setNoOfItemsFound(new String());
homePage.setOwnedBy(urlOwnedBy);
homePage.setPageType(scraper.getPageTypeToScrape());
homePage.setPageUrl(startUrl);
proxy = getInitialisedProxy();
scraper.setNavigator(proxy.getNavigator());
scraper.setStartUrl(startUrl);
try {
scraper.initialize();
} catch (MyException e) {
if (status == false){
throw new Exception(MyException.NOTFOUND);
}
}
}
}
}
I'm using sellinium. Is there any chance that I'm getting the issue because of selenium?
Look at code and compare it with your code.
public static void main(String []args)
{
Runnable inst=new Runnable()
{
public void run()
{
System.out.println("Thread statement!");
}
};
Thread thrd=new Thread(inst);
thrd.start();
}
How did you come to know run method is not executed . didu u put a trace on the run method?
//Old
new Thread(niidleThread,"scraper"); scraper.start()
// new
new Thread(srThread); or
new Thread(srThread,"scraper");
Try the new one i have given above;
Just from a cursory review of your code... I see that you might have gone a little thread-happy. Consider:
ScrapeThread srThread = new ScrapeThread("srThread"); // This is creating your ScrapeThread object (which should really implement the Runnable interface)
Thread scraper = new Thread(srThread); // This is creating a thread which wraps another thread... take this out.
srThread.setSiteToScrape(site);
srThread.setPageTypeToScrape(startPageToScrape);
srThread.setTypeToScrape(typeToScrape);
ArrayList<String> listOfValues = ScraperStore.getNextUrlToScrape(startPageToScrape, site);
srThread.setTypeToScrape(typeToScrape);
try {
srThread.setUrlOwnedBy(listOfValues.get(0));
srThread.setStartUrl(listOfValues.get(1));
scraper.start(); // You would want to replace this with srThread.start(); once fixing the items I addressed above
boolean state=scraper.isAlive();
scrapeThreads.add(scraper);
}
catch (Exception e) {
e.printStackTrace();
}
http://www.javabeginner.com/learn-java/java-threads-tutorial might help you out a bit.