How to access a given Java thread - java

Basically, I want to be able to run multiple threads - these threads will use sleep commands for a given period. I want to be able to manipulate the duration of these sleep threads based on user input after the thread has already been running for a period.
For example:
Starting the thread from classA...
private final ExecutorService scheduler = Executors.newCachedThreadPool();
public void startJob(Job job, List <Object> objectList) {
//Store the results of this in a map using a future and the id of job??
scheduler.submit(jobThreadInterface.create(job, objectList));
}
JobThreadInterface starts classB...
public class ClassB implements Runnable{
private Job job;
private List <Object> objectList;
private int changeSleepDuration;
public ClassB (Job job, List <Object> objectList){
this.job = job;
this.objectList= objectList;
}
public void run() {
//It will keep looping through this sleep command until there are no more objects left...
for (Object object : objectList){
if (object.getSleepNumber() > 0){
Thread.sleep(object.getSleepNumber() + changeSleepDuration);
}
}
public setChangeSleepDuration(int i){
changeSleepDuration = i;
}
}
}
So basically, what I want to do is access the setChangeSleepDuration method in ClassB from classA for any thread that I want to access. Is this possible and if so what is the best way?
Thanks,

I suppose that jobThreadInterface.create(job, objectList) does create an instance of ClassB. In that method, you could store the reference to ClassB in a collection that you can access later.
So something like:
ClassB runnable = jobThreadInterface.create(job, objectList);
list.add(runnable);
scheduler.submit(runnable);
And later in your code:
list.get(0).setChangeSleepDuration(1000);
Or you could store the runnables in a map to associate them with some keys that will help you retrieve them later on.

You could keep a hold of the Job instance. Then when the thread starts working on the job, save the thread as an attribute of your job. Then classA already knows the Job, so it can access the thread.
Alternatively, you might simply want to save that changeSleepDuration value in the job itself. It comes down to semantics. What does changeSleepDuration represent (a thread control, or is it part of the job?). Sounds like the latter. I'd go for option two.

Related

Java Supporting Embedded Multi-Threading

Need help with Java multiple threading
I have a case as below:
There are many records. Each record has about 250 fields. Each field needs to be validated against on a predefined rule.
So I defined a class, FieldInfo, to represent each field:
public class FieldInfo {
private String name;
private String value;
private String error_code;
private String error_message;
// ignore getters and setters
}
a class Record to represent a record:
public class Record {
List<FieldInfo> fields;
// omit getter and setter here
}
and the rule interface and class:
public interface BusinessRule {
// validating one field needs some other fields' value in the same record. So the list of all fields for a certain record passed in as parameter
public FieldInfo validate(List<FieldInfo> fields);
}
public class FieldName_Rule implements BusinessRule {
public FieldInfo validate(List<FieldInfo> fields) {
// will do
// 1. pickup those fields required for validating this target field, including this target field
// 2. performs validation logics A, B, C...
// note: all rules only read data from a database, no update/insert operations.
}
}
User can submit 5000 records or more at a time for process. The performance requirement is high. I was thinking to have multiple threads for the submitted, for example 5000, records (means one thread run several records), and in each thread, fork another multiple threads on each record to run rules.
But unfortunately, such embedded multi-threading always died in my case.
Here are some key parts from the above solution:
public class BusinessRuleService {
#Autowired
private ValidationHandler handler;
public String process(String xmlRequest) {
List<Record> records = XmlConverter.unmarshall(xmlRequest).toList();
ExecutorService es = Executors.newFixedThreadPool(100);
List<CompletableFuture<Integer> futures =
records.stream().map(r->CompletableFuture.supplyAsync(()-> handler.invoke(r), es)).collect(Collectors.toList());
List<Integer> result = future.stream().map(CompletableFuture::join).collect(Collectors.toList());
System.out.println("total records %d processed.", result.size());
es.shutdown();
return XmlConverter.marshallObject(records);
}
}
#Component
public class ValidationHandlerImpl implements ValidationHandler {
#Autowired
private List<BusinessRule> rules;
#Override
public int invoke(Record record) {
ExecutorService es = Executors.newFixedThreadPool(250);
List<CompletableFuture<FieldInfo> futures =
rules.stream().map(r->CompletableFuture.supplyAsync(()-> r.validate(record.getFields()), es)).collect(Collectors.toList());
List<FieldInfo> result = future.stream().map(CompletableFuture::join).collect(Collectors.toList());
System.out.println("total records %d processed.", result.size());
es.shutdown();
return 0;
}
}
The workflow is:
User submits a list of records in an xml string format. One of the application endpoint launches the process method in a BusinessRuleService object. The process uses CompletableFuture to compose tasks and submit the tasks to a ExecutorService which has a thread pool of size 100. Each task in the CompletableFuture list then launches ValidationHandler object. The ValidationHandler object composes another CompletableFuture task and submit the task to another ExecutorService which has the pool size the same as the rule list size.
The above solution is proper?
Note: my current solution is: the submitted records are processed in sequence. And the 250 rules are processed in parallel for each record. With this solution, it takes more than 2 hours for 5000 records. Such poor performance is not acceptable by business.
I am very new to concurrent/multi-threading programming.
Much appreciate for all kind of helps!
This is a well known "single producer - multiple consumers" pattern. The classic solution is to create a BlockingQueue<Record> queue, and put records there at the pace of their reading. On the other end of the queue, a number of working threads read records from the queue and process them (in our case, validate the fields):
class ValidatingThread extends Tread {
BlockingQueue<Record> queue;
FieldName_Rule validator = new FieldName_Rule();
public Validator (BlockingQueue<Record> queue) {
this.queue = queue;
}
public void run() {
Record record = queue.take();
validator.validate(collectFields(record));
}
}
The optimal number of threads equals to the Runtime.getRuntime().availableProcessors().
Start them all at the beginning, and do not use "embedded multi-threading".
The task how to stop the threads after all the records are processed, is left as a learning assignment.

Modifying a runnable object after it has been submitted to ExecutorService?

Is it possible to modify the runnable object after it has been submitted to the executor service (single thread with unbounded queue) ?
For example:
public class Test {
#Autowired
private Runner userRunner;
#Autowired
private ExecutorService executorService;
public void init() {
for (int i = 0; i < 100; ++i) {
userRunner.add("Temp" + i);
Future runnerFuture = executorService.submit(userRunner);
}
}
}
public class Runner implements Runnable {
private List<String> users = new ArrayList<>();
public void add(String user) {
users.add(user);
}
public void run() {
/* Something here to do with users*/
}
}
As you can see in the above example, if we submit a runnable object and modify the contents of the object too inside the loop, will the 1st submit to executor service use the newly added users. Consider that the run method is doing something really intensive and subsequent submits are queued.
if we submit a runnable object and modify the contents of the object too inside the loop, will the 1st submit to executor service use the newly added users.
Only if the users ArrayList is properly synchronized. What you are doing is trying to modify the users field from two different threads which can cause exceptions and other unpredictable results. Synchronization ensures mutex so multiple threads aren't changing ArrayList at the same time unexpectedly, as well as memory synchronization which ensures that one thread's modifications are seen by the other.
What you could do is to add synchronization to your example:
public void add(String user) {
synchronized (users) {
users.add(user);
}
}
...
public void run() {
synchronized (users) {
/* Something here to do with users*/
}
}
Another option would be to synchronize the list:
// you can't use this if you are iterating on this list (for, etc.)
private List<String> users = Collections.synchronizedList(new ArrayList<>());
However, you'll need to manually synchronize if you are using a for loop on the list or otherwise iterating across it.
The cleanest, most straightforward approach would be to call cancel on the Future, then submit a new task with the updated user list. Otherwise not only do you face visibility issues from tampering with the list across threads, but there's no way to know if you're modifying a task that's already running.

Storing multiple Threads in Java

Suppose I have a class which implements Runnable interface, and I am to make 5 instances of given class in the main program. I would like to store them either in array, or a collection. Since the class implements Runnable it is my understanding that the only way I can store it is in a thread container such as Thread[]. However if I do this I can't use classes overridden toString() method for example, or any other custom method/field.
public class LittleClass implements Runnable{
public void run(){
}
}
public static void main(String[] args){
Thread[] smallClasses = new Thread[5];
// initialize and so...
smallClasses[i].customField//not accessible
System.out.println(smallClasses[i])//gives Thread[Thread-X,X,]
}
You should consider using an ExecutorService. Then you keep an array of your job classes and submit them to the service to be run.
// create a thread pool with as many workers as needed
ExecutorService threadPool = Executors.newCachedThreadPool();
// submit your jobs which should implements Runnable
for (YourRunnable job : jobs) {
threadPool.submit(job);
}
Once you have submitting your jobs, you shut down the service, wait for it to finish, and then you can interrogate your jobs to get information from them.
// shuts the pool down but the submitted jobs still run
threadPool.shutdown();
// wait for all of the jobs to finish
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
// now go back and print out your jobs
for (YourRunnable job : jobs) {
System.out.println(jobs.toString());
}
Here's a good tutorial on the subject.
You can create your custom class which implements Runnable and then story an array of those custom classes.
So, for instance, in the code you wrote above, you can always use
LittleClass[] objs = new LittleClass[4];
for(int i = 0; i < objs.length; i++) {
objs[i] = new LittleClass();
}

Multithreaded access to add, get, remove methods, using recursion and Java and a Tree structure

I have a tree structure that I am trying to use a recursive method to add, get, or remove an item. I would like to be able to introduce a new thread for every child node that I find with an iterator. I currently pass the node into the recursive method when I call it. I would like to be able to start a thread and tell that thread to call that method. How would I do something similar to saying new thread, thread.callMethod()? I need to have a Runnable interface and a run method apparently? However this seems to complicate things much more than necessary (I already have method names). Does anyone know a good way to do this using run(..), or does anyone know a better way to do this without using run(..). Thanks.
Thank you for your answers. I had been thinking that I need to somehoe get a new instance of a node running on a new thread, but that is not the case. The node just occupies space in memory and the thread is reference to the method code that is executed on the instance living in memory (my CS 302 TA is already disagreeing with me in my head). So.. I had been thinking about enums, but I was thinking that I might somehow need to have all my nodes running on separate threads during instantiation, or else, have the methods actually written in new classes that implement runnable.
In other words,
public class TreeMethods implements Runnable
{
...
run(.. node, .. params, .. enum)
{
switch(enum)
case(add)
{
myThreadInstanceMethod(node);
}
...
}
myThreadInstanceMethod(..) {..}
}
Thanks. I didn't know that I was asking this question, but you've just simplified my thread management design process greatly.
You can't do it without a Runnable or Callable object. The proper way to do what you want is to create a Runnable class that takes your object and calls the appropriate method on that object.
public class MyRunnable implements Runnable {
private MyObject obj;
public MyRunnable(MyObject obj) {
this.obj = obj;
}
public void run() {
obj.someMethod();
}
}
If you need to call one of a couple methods then you can use an enum for this. If you need to pass in arguments then you can add them to the constructor.
With threads, it's always recommended that you use the Executors class and the ExecutorService thread pools. This will limit the number of threads created by your recursive algorithm and keep the thread particulars hidden.
// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
// or you can create an open-ended thread pool
// ExecutorService threadPool = Executors.newCachedThreadPool();
while (recursing) {
threadPool.submit(new MyRunnable(myObject));
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
...
You may need something like this:
Your runnable:
public class ComputeNode implements Runnable {
private Node node;
public ComputeNode(Node nodeToCompute) {
this.node = nodeToCompute;
}
#Override
public void run() {
computeOnNode(node);
}
}
How to start it:
Runnable compute = new ComputeNode(nodeToComputeOn);
Thread t = new Thread(comute);
t.start();
ComputeOnNode() is your own method written somewhere.

How often is a thread executed? My Observer pattern gone wrong?

The following is a simplified version of my current code. I am pretty sure I am not doing any thing wrong syntax-wise, and I can't locate my conceptual mistake.
This is sort of an observer pattern I tried to implement. I could not afford to inherit from Java.utils.observable as my class is already complicated and inherits from another class.
There are two parts here:
There's a Notifier class implementing Runnable :
public class Notifier implements Runnable{
public void run()
{
while(true)
{
MyDataType data = getData();
if(data.isChanged()==true)
{
refresh();
}
}
}
}
And then there is my main class which needs to respond to changes to MyDataType data.
public class abc {
private MyDataType data;
public void abc(){
Notifier notifier = new Notifier();
Thread thread = new Thread(notifier);
thread.start();
}
public MyDataType getData(){
return this.data;
}
public void refresh(){
MyDatatype data = getData();
//Do something with data
}
}
The problem : What's happening is that the notifier is calling refresh() when 'data' changes. However inside refresh(), when I do getData(), I am getting the old version of 'data'!
I should mention that there are other parts of the code which are calling the refresh() function too.
What am I overlooking?
Any other better solutions to this problem?
How should I approach designing Subject-Observer systems if I can't apply the default Java implementation out of the box?
when I do getData(), I am getting the old version of 'data'!
Your data field is shared among more than one thread so it must be marked with the volatile keyword.
private volatile MyDataType data;
This causes a "memory barrier" around the read and the the write that keeps the value visible to all threads. Even though the notifier thread is calling getData(), the value for data is being retrieved out if its memory cache. Without the memory barrier, the data value will be updated randomly or never.
As #JB mentioned in the comments, the volatile protects you against a re-assignment of the data field. If you update one of the fields within the current data value, the memory barrier will not be crossed that the notifier's memory will not be updated.
Looking back at your code, it looks like this is the case:
if(data.isChanged()==true)
{
refresh();
}
If data is not being assigned to a new object then making data to be volatile won't help you. You will have to:
Set some sort of volatile boolean dirty; field whenever data has been updated.
Update or read data within a synchronize block each and every time.
First, your data variable might be cached, so you will always need to get the latest value by making it volatile.
Second, what you are doing here is a producer / consumer pattern. This pattern is usually best implemented with messages. When you receive new data, you could create an immutable object and post it to the consumer thread (via a thread safe queue like a BlockingQueue) instead of having a shared variable.
Something along these lines:
public class Notifier extends Thread{
private BlockingQueue<E> consumerQueue = null;
public setConsumerQueue(BlockingQueue<E> val){
consumerQueue = val;
}
// main method where data is received from socket...
public void run(){
while(!interrupted()){
data = ... // got new data here
if(!data.isChanged()) continue;
// Post new data only when it has changed
if(consumerQueue!=null) consumerQueue.offer(data);
}
}
}
public class Consumer extends Thread{
private BlockingQueue<E> consumerQueue = new BlockingQueue<E>();
public Consumer (Producer val){
val.setConsumerQueue(consumerQueue);
}
public void run(){
while(!interrupted()){
data = consumerQueue.take();// block until there is data from producer
if(data !=null) processData(data);
}
}
}

Categories