run static method from a thread pool in java - java

What is the best way to run a static method in several threads, using a thread pool?
Also I trying to pass an argument to the static method. something like
Class A{
public static runTask(int i){
....
}
}
and from a main:
ThreadPool pool = new ThreadPool(5, "poolname");
for(int i=1; i<10; i++){
A.runTask(i) // but on a new thread...
}
Thanks!

Have a look at the documentation for java.util.concurrent.Executors. It should meet your needs. Here is a simple example of using it:
public class ExecutorServiceTest {
static ExecutorService threadPool = Executors.newCachedThreadPool();
public static void main(String[] args) throws Exception {
// Queue 10 executions of someTask into the threadPool
for(int i = 0; i < 10; i++) {
runSomeTaskInThreadPool();
}
// the shutdown method causes the executor to:
// 1. stop accepting new tasks, and
// 2. allow previously queued jobs to complete, and
// 3. shut down all pooled threads once all jobs are complete
threadPool.shutdown();
// block until the threadPool has finished shutting down,
// which indicates that all tasks have finished executing
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}
private static void runSomeTaskInThreadPool() {
Future future = threadPool.submit(new Runnable() {
public void run() {
someTask();
}
});
// TODO: Maybe keep track of futures to monitor success/failure of task
}
static AtomicInteger counter = new AtomicInteger();
public static void someTask() {
System.out.println("someTask: " + counter.incrementAndGet()
+ " on thread: " + Thread.currentThread());
}
}

Please find the detailed implementation guides:
http://java.sun.com/developer/Books/javaprogramming/threads/chap13.pdf

Related

Which threading mechanism to use for tasks that enqueue other tasks?

I'm using a task that creates other tasks. Those tasks in turn may or may not create subsequent tasks. I don't know beforehand how many tasks will be created in total. At some point, no more tasks will be created, and all the task will finish.
When the last task is done, I must do some extra stuff.
Which threading mechanism should be used? I've read about CountDownLatch, Cyclic Barrier and Phaser but none seem to fit.
I've also tried using ExecutorService, but I've encountered some issues such as the inability to execute something at the end, and you can see my attempt below:
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class Issue {
public static void main(String[] args) throws InterruptedException {
var count = new AtomicInteger(1);
var executor = Executors.newFixedThreadPool(3);
class Task implements Runnable {
final int id = count.getAndIncrement();
#Override
public void run() {
try {
MILLISECONDS.sleep((long)(Math.random() * 1000L + 1000L));
} catch (InterruptedException e) {
// Do nothing
}
if (id < 5) {
executor.submit(new Task());
executor.submit(new Task());
}
System.out.println(id);
}
}
executor.execute(new Task());
executor.shutdown();
// executor.awaitTermination(20, TimeUnit.SECONDS);
System.out.println("Hello");
}
}
This outputs an exception because tasks are added after shutdown() is called, but the expected output would be akin to:
1
2
3
4
5
6
7
8
9
Hello
Which threading mechanism can help me do that?
It seems pretty tricky. If there is even a single task that's either in the queue or currently executing, then since you can't say whether or not it will spawn another task, you have no way to know how long it may run for. It may be the start of a chain of tasks that takes another 2 hours.
I think all the information you'd need to achieve this is encapsulated by the executor implementations. You need to know what's running and what's in the queue.
I think you're unfortunately looking at having to write your own executor. It needn't be complicated and it doesn't have to conform to the JDK's interfaces if you don't want it to. Just something that maintains a thread pool and a queue of tasks. Add the ability to attach listeners to the executor. When the queue is empty and there are no actively executing tasks then you can notify the listeners.
Here's a quick code sketch.
class MyExecutor
{
private final AtomicLong taskId = new AtomicLong();
private final Map<Long, Runnable> idToQueuedTask = new ConcurrentHashMap<>();
private final AtomicLong runningTasks = new AtomicLong();
private final ExecutorService delegate = Executors.newFixedThreadPool(3);
public void submit(Runnable task) {
long id = taskId.incrementAndGet();
final Runnable wrapped = () -> {
taskStarted(id);
try {
task.run();
}
finally {
taskEnded();
}
};
idToQueuedTask.put(id, wrapped);
delegate.submit(wrapped);
}
private void taskStarted(long id) {
idToQueuedTask.remove(id);
runningTasks.incrementAndGet();
}
private void taskEnded() {
final long numRunning = runningTasks.decrementAndGet();
if (numRunning == 0 && idToQueuedTask.isEmpty()) {
System.out.println("Done, time to notify listeners");
}
}
public static void main(String[] args) {
MyExecutor executor = new MyExecutor();
executor.submit(() -> {
System.out.println("Parent task");
try {
Thread.sleep(1000);
}
catch (Exception e) {}
executor.submit(() -> {
System.out.println("Child task");
});
});
}
}
If you change your ExecutorService to this:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
You could then use the count functions to wait:
while(executor.getTaskCount() > executor.getCompletedTaskCount())
{
TimeUnit.SECONDS.sleep(10L);
}
executor.shutdown();
System.out.println("Hello");

How do I get my threads to run in an orderly sequence?

I'm learning Java threads and want my code to output threads 0-9 in sequential order. I used the synchronized keyword but I don't get the results I expect.
What should I do to correct my code?
public class MyThread extends Thread {
private static final int threadMax = 10;
private static int runCount = 0;
public void printThread() {
synchronized (this) {
while (runCount++ < 100) {
System.out.println(runCount + ": " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void run() {
printThread();
}
public static void main(String[] args) {
for (int i = 0; i < threadMax; i++) {
new MyThread().start();
}
}
}
It is not working as every time you are creating new MyThread object and you are synchronized over that new object. So, every Thread you created will get a lock on the diffrent object. So, you should pass a common object to take the lock like below.
class MyThread extends Thread {
private static int runCount = 0;
Object lock;
public MyThread(Object lock) {
this.lock = lock;
}
public void printThread() {
synchronized (lock) {
// your code here
}
}
//.........
}
And then call it like :
Object lock = new Object();
for (int i = 0; i < threadMax; i++) {
new MyThread(lock).start();
}
However, the above program will not ensure you that it will run in sequence. There are several ways to do that. You can use wait() and notify() to achieve your goal. Refer the below example :
public void printThread() {
while (runCount < 90) {
synchronized (lock) {
while (runCount % 10 != remainder) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(runCount + ": " + Thread.currentThread().getName());
runCount++;
lock.notifyAll();
}
}
}
And call the thread like :
Object lock = new Object();
for (int i = 0; i < 10; i++) {
new MyThread(lock, i).start();
}
You are synchronizing the context of the thread, which is different for each one. You should put into the synchronized key any common object for all diferent threads. This won't make them run in any certain secuence, just to wait each other to end.
If you want to test the synchronized keyword for any purpose, you could pass the constructor a common variable and use it in every thread:
public class MyThread extends Thread {
private static final int threadMax = 10;
private static int runCount = 0;
private Object test; //Object pointing main method
public MyThread(Object test){
this.test = test; //This won't copy values as it is an object and not a number, string...
}
public void printThread() {
synchronized (test) { //Same object for all threads
while (runCount++ < 100) {
System.out.println(runCount + ": " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void run() {
printThread();
}
public static void main(String[] args) {
Object test; //common object
for (int i = 0; i < threadMax; i++) {
new MyThread(test).start();
}
}
}
If you want also to make them start in order, you should "synchronize" the loop making wait and notify calls.
Anyway, the point about multithreading is to have several threads running at the "same" time and not in sequence, as that would be the same as a linear execution.
You have several tasks that you want to delegate to threads but have them executed sequentially.
As others have pointed out, wait & notify can help you achieve that : wait until Nth have finished then notify the next. However, if you wait/notify inside your printThread method, as all your threads are waiting simultaneously on the same lock, there is no guaranties that N+1th thread will be next. So you may have
1: thread-1
...
10: thread-1
11: thread-5
...
20: thread-5
21: thread-2
...
If that's ok for you, you're done. However, in a situation where you specifically want your threads to be ordered, what you need is a waiting queue (FIFO : First In First Out).
To achieve that, you can use the awesome ExecutorService. Be aware however that they hide the Threads from you and picking that solution should not be at the cost of understanding the basics of them beforehand.
An ExecutorService is a very convenient class that can receive tasks (in the form of a Runnable, see below) and will execute them in separate Threads.
Here, I'm using a SingleThreadExecutor which execute the submitted tasks sequentially. So all you have to do is call it's execute method with your tasks as arguments, and the ExecutorService will run them in the right order, one after the other.
Here's what you can do with a few notes :
public class ThreadRunner {
// Note : Constants are usually all uppercase in Java
private static final int MAX_THREADS = 10;
private final int threadName;
public ThreadRunner(int threadName) {
this.threadName = threadName;
}
public void printThread() {
// Note: For loops are better than while when you already know the number of iterations
for (int runCount = 0; runCount < 10; runCount++) {
System.out.println(runCount + "th run from thread " + threadName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < MAX_THREADS; i++) {
int threadName = i + 1;
// Submit a task to the executor
executorService.execute(() -> new ThreadRunner(threadName).printThread());
}
// Nicely ask for the executor to shutdown.
// Then wait for already submitted tasks to terminate.
executorService.shutdown();
try {
executorService.awaitTermination(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I changed a few details, here are the reasons :
Thread creation : don't inherit from Thread
I would advise you not to inherit from Thread, but create a local instance of it, as all you need is to use a Thread ; you don't want to be a Thread :
public static void main(String[] args) {
// Using Java 1.8+ lambda
Thread lambdaThread = new Thread(() -> System.out.println("Hello from a lambda in a Thread"));
lambdaThread.start();
// Using an anonymous class for java <1.8
Thread anonClassThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Hello from an anonymous class in a Thread");
}
});
anonClassThread.start();
}
You're creating a new Thread passing a Runnable as constructor argument, using either lambda or anonymous class, depending of your Java version.
A Runnable is simply a portion of code that will be executed (by a Thread, in this case).
Same apply to ExecutorService, it's execute methode takes a Runnable which I've created through lambdas.
Sharing static counter between threads
Your line private static int runCount = 0; is a static field, which means it is shared by all instances of the class MyThread. When you increase it in a thread, all threads will read (and write) to the same variable.
If your threads were running sequentially, the first would do it's 100 iterations, then when the second thread starts, runCount is already at 100 and you're not entering your while loop. If that wasn't intended, it may be confusing when you'll test your code.
Based on your expected output in a comment, I believe you want your threads to do 10 iterations each, not share a pool of 100 iterations and manage somehow to have each of them only perform 10.
Having the name of the thread belong to each ThreadRunner
Small detail here : previously, you were creating 10 threads. Here, the ExecutorService only creates one that he reuse for each task you submit. So Thread.currentThread().getName() would always be thread-1.
You wouldn't be able to see which task is running without this field.
If each task is started after the previous, you don't need 10 Threads, but a single Thread performing the 10 tasks sequentially.
I've been as complete as possible, but some points might be a little bit tricky, so don't hesitate to ask for clarifications!

Only one thread running from ExecutorService newFixedThreadPool of size 5

I am trying to learn the behavior of ExecutorService newFixedThreadPool. I assign work to the executorService and expect it to be done by multiple threads.
The scenario is simple.
I initialize thread pool of size 5. And then I assign work to executor service.
But I see only one thread is handling the work.
Shouldn't it be handled by more than one thread available in the pool.
Code:
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.execute(new Runnable() {
public void run() {
int k =0;
while (k++<5){
System.out.println("Active Thread "+Thread.currentThread().getName());
}
}
});
Here is the complete code
jdoodle.com/a/bRP
The output I got is
Active Thread pool-1-thread-1
Active Thread pool-1-thread-1
Active Thread pool-1-thread-1
Active Thread pool-1-thread-1
Active Thread pool-1-thread-1
The output I was expecting was:
More threads participating in the work.
EDIT
Essentially I want to replicate this behavior using ExecutorService
package Threading;
public class ThreadDeleteme {
public static void main(String[] args) {
Work w = new Work();
Thread t1 = new Thread(w);
t1.setName("Thread 1 ");
Thread t2 = new Thread(w);
t2.setName("Thread 2 ");
Thread t3 = new Thread(w);
t3.setName("Thread 3 ");
t1.start();
t2.start();
t3.start();
System.out.println("ThreadDeleteme.main()");
}
}
class Work implements Runnable {
Integer i = 0;
#Override
public void run() {
while (i < 100) {
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
}
}
}
Can you please tell me where my understanding is going wrong.
Thanks
you need to create a number of tasks, instead you created just a single one only. So, something like the following should work for you. But, if the task finishes faster than you create another one, it will probably not hit all the threads in any case.
ExecutorService executorService = Executors.newFixedThreadPool(5);
int k =0;
while (k++<5){
executorService.execute(new Runnable() {
public void run() {
System.out.println("Active Thread "+Thread.currentThread().getName());
});
}
};
You have created ONE thread that prints current thread name ( =Active Thread pool-1-thread-1) 5 times.
Make 5 runnable instance and submit them to the executor service
[UPDATE]
public class Main {
public static void main(String[] args) {
Work w = new Work();
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(w);
executorService.submit(new Work()); // set new runnable tasks here
executorService.submit(new Work());
System.out.println("ThreadDeleteme.main()");
}
}
class Work implements Runnable {
Integer i = 0;
#Override
public void run() {
while (i < 100) {
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
}
}
}
For naming issue,
You'll have to use an ExecutorService implementation that allows you to set the ThreadFactory 1 used to create threads, Pass an instance that creates threads with the proper names.
ThreadFactory DOC
You're using same thread to print loop ,but not calling method with different thread, thread doesn't divide task automatically you have to assign task to them.Your main() methods look like
public static void main(String[] args){
ExecutorService executorService = Executors.newFixedThreadPool(5); //here you defined thread pool size
executorService.submit(new Work()); //added first thread to pool
executorService.submit(new Work()); //added second thread
executorService.submit(new Work()); //added third thread
}
And your Work class:
class Work implements Runnable {
int i = 0;
#Override
public void run() {
while (i < 100) {
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
}
}
}

Simple queue and multi-threading

I have to process a lot of files. I wrote simple Java program that does the job, but it is too slow.
I need more than 1 working thread.
Im totally new with Java and Java multithreading.
Here is my code (simplified):
public static void main(String[] args)
{
// some queue here?
for (int i = 1; i < 8000000; i++)
{
processId(i);
}
}
public static void processId(int id)
{
try
{
// do work
System.out.println("Im working on: " + Integer.toString(id));
}
catch (Exception e)
{
// do something with errors
System.out.println("Error while working on: " + Integer.toString(id));
}
}
How can I add simple queue with 8 threads?
You should look into Executors.
You can create a thread pool of 8 threads using:
ExecutorService executor = Executors.newFixedThreadPool(8);
Then submit your tasks inside your loop the following way:
final int finalId = i; // final is necessary to be enclosed in lambda
executor.submit(() -> processId(finalId));
Or prior to java 8:
final int temp = i; // final is necessary to be enclosed in anonymous class
executor.submit(new Runnable() {
public void run() {
processId(finalId);
}
});
Don't forget to shutdown the thread pool when not needed anymore, as mentioned in the documentation. Here is an example from the doc:
private void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
You should look into ExecutorService. This will make multithreading easy. An example:
Main code:
ExecutorService pool = Executors.newFixedThreadPool(8);
for (int i = 1; i < 8000000; i++) {
pool.submit(new intProcessingTask(i));
}
pool.shutdown();
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
// all tasks have now finished (unless an exception is thrown above)
intProcessingTask code:
private static class DownloadTask implements Runnable {
private int id;
public DownloadTask(int id) {
this.id = id;
}
#Override
public void run() {
System.out.println("Im working on: " + Integer.toString(id));
}
}
This is slightly longer than the the other answer, but does pretty much the same thing, and works on Java 7 and earlier.
There are many ways in Java for processing mulithreading. Base on your question that you need a queue, I think the most simple version is use Java ExecutorService. You can see this code:
public static void main(String[] args) {
// creating a thread pool with maximum thread will be 8
ExecutorService executorService = Executors.newFixedThreadPool(8);
for (int i = 0; i < 8000000; i++) {
final int threadId = i;
executorService.execute(new Runnable() {
public void run() {
processId(threadId);
}
});
}
}
ExecutorService has some methods:
execute(Runnable)
submit(Runnable)
submit(Callable)
invokeAny(...)
invokeAll(...)
I recommend you view this link: ExecutorService tutorial for clear explanation.
Hope this help :)

java callback functions in a multi threaded environment

In AJAX, suppose i submit a request asynchronously. When the reposne returns , it executes a callback function.
What is the best way to implement the same in a java multithreaded environment?
i.e Main thread creates a child thread and submits a task and then the child thread returns a callback function needs to be executed by the main thread.
Is this possible? In main thread I can do wait() and in child thread i can do notify() but in that case the main thread will wait until the child thread finishes.
But in AJAX the main thread continues its operation...that is what i want
You could use an ExecutorService to do tasks on the background and then use the methods of the Future you get back to wait for the result. For example:
class Main {
private static final ExecutorService es = Executors.newCachedThreadPool();
public static void main(final String... args) throws Throwable {
List<Future<Integer>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(asyncSum(i, i*i));
}
// here, in the main thread, you can do whatever you want
// while the calculations are performed in background threads
// ...
// after the main thread finishes what it was doing, it
// can process the futures
for (final Future<Integer> result : results) {
System.out.println(result.get());
}
}
// this method launches a calculation on a worker thread and immediately
// returns a Future, which is a reference to the result of the calculation
// once it is completed
private static Future<Integer> asyncSum(final int a, final int b) {
return es.submit(new Callable<Integer>() {
#Override public Integer call() throws Exception {
return a + b;
}
});
}
}
In the example above, the main thread will block until the first computation is done, then print it. Then block until the second computation is done, then print it, etc.
If you wish to print the results as they become available (in an unspecified order), then you could use a CompletionService, and instead of having a list of results and iterating on it, you'd get your futures from the CompletionService itself through its .take() method, that blocks until a computation is finished, or .poll(), which returns a Future if there there are finished computations, or null if there are no computations finished -- this way your main thread will never block.
The following example uses a CompletionService. It shows a main thread that never blocks, uses background threads to do calculations and process the results as they become available:
class Main {
public static void main(String[] args) throws Throwable {
final ExecutorService es = Executors.newCachedThreadPool();
final CompletionService<Integer> cs = new ExecutorCompletionService<>(es);
submitSomeCalculations(cs);
while (true) {
doMainThreadWork();
processFinishedCalculations(cs);
}
}
private static void submitSomeCalculations(final CompletionService<Integer> cs) {
for (int i = 0; i < 10; i++) {
submitAsyncSum(cs, i, i * i);
}
}
private static void submitAsyncSum(final CompletionService<Integer> cs, final int a, final int b) {
cs.submit(new Callable<Integer>() {
#Override public Integer call() throws Exception {
Thread.sleep(100 + (long) (Math.random() * 900));
return a + b;
}
});
}
private static void processFinishedCalculations(final CompletionService<Integer> cs) throws ExecutionException, InterruptedException {
while (true) {
final Future<Integer> result = cs.poll();
if (result == null) {
System.out.println("> no finished results...");
break;
} else {
System.out.println("> result available: " + result.get());
}
}
}
static void doMainThreadWork() {
System.out.println("work from main thread...");
}
}

Categories

Resources