I have a problem with finishing my main thread. When threads "finish" (maybe not, I don't know, but I have a right result in static variable "nextNumber"), the program still works.
I suppose that the Executor doesn't terminate because he still waits for another threads to run.
Earlier I used my own runnable class and hadn't to take care about terminating it.
My code:
private static long nextNumber = 0;
public static void main(String[] args) {
Runnable firstCounter = () -> {
for (int i = 0; i < 1000000; i++)
increment("Thread 1");
};
Runnable secondCounter = () -> {
for (int i = 0; i < 1000000; i++)
increment("Thread 2");
};
Executor executor = Executors.newFixedThreadPool(2);
executor.execute(firstCounter);
executor.execute(secondCounter);
System.out.println(nextNumber);
}
synchronized private static void increment(String threadName) {
System.out.println(threadName + " " + ++nextNumber);
}
First you need to use ExecutorService and then you need to shut it down.
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.shutdown(); //Prevents executor from accepting new tasks
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); //Waits until currently executing tasks finish but waits not more then specified amount of time
Related
I need to execute a single task by multiple threads, such that when the first thread finishes and before any other thread finishes, all the threads are stopped and start the same task all over again. This should be performed n times.
My attempt is using Callable<V> and the method invokeAny() (that is why I use the set) but not sure how to accomplish the goal.
ExecutorService executor = Executors.newFixedThreadPool(10);
Callable<String> task = () -> {
someTask();
return "";
};
Set<Callable<String>> tasks = new HashSet<>();
IntStream.range(0, n).forEach(i -> {
tasks.add(task);
executor.submit(task);
});
How to finish this? or any better solution?
Here's one suggestion:
class Task implements Callable<Integer> {
private final static Random RND = new Random();
#Override
public Integer call() throws Exception {
try {
// Work on task for a random duration
Thread.sleep(RND.nextInt(5000));
} catch (InterruptedException e) {
System.err.println("I was interrupted."
+ "Someone else probably solved the task before me.");
return -1;
}
// Return some dummy value
return RND.nextInt();
}
}
class Scratch {
public static void main(String[] args) throws InterruptedException {
final int numWorkers = 3; // number of tasks to run in parallel
ExecutorService executor = Executors.newFixedThreadPool(numWorkers);
// Solve task 5 times. (Change it to while (true) { ...} if you like.)
for (int i = 0; i < 5; i++) {
CompletionService<Integer> completionService =
new ExecutorCompletionService<>(executor);
Future<?>[] futures = new Future<?>[numWorkers];
for (int j = 0; j < numWorkers; j++) {
futures[j] = completionService.submit(new Task());
}
Future<Integer> firstToComplete = completionService.take();
try {
Integer result = firstToComplete.get();
System.err.println("We got a result: " + result);
} catch (ExecutionException e) {
// Should not happen. Future has completed.
}
// Cancel all futures (it doesn't matter that we're cancelling
// the one that has already completed).
for (int j = 0; j < numWorkers; j++) {
futures[j].cancel(true);
}
}
executor.shutdown();
}
}
If the task you're solving does not respond to interrupts, passing true to cancel(...) won't help. In that case I'd suggest you do the following changes:
Create an AtomicBoolean done variable in the outer for loop.
Pass this to the constructor to Task and save it in a field in Task.
In the task solving process, check done flag ever so often, and cancel the attempt if done is true.
Instead of calling cancel on the tasks after the first result is in, set done to true and wait for the other threads to return.
I'm having a hard time understanding how ExecutorService works in Java 8. I was trying to understand some of the code on this website: https://crunchify.com/hashmap-vs-concurrenthashmap-vs-synchronizedmap-how-a-hashmap-can-be-synchronized-in-java/
Particularly at the end where he tests the runtimes of the different maps. This is the code:
public class CrunchifyConcurrentHashMapVsSynchronizedMap {
public final static int THREAD_POOL_SIZE = 5;
public static Map<String, Integer> crunchifyHashTableObject = null;
public static Map<String, Integer> crunchifySynchronizedMapObject = null;
public static Map<String, Integer> crunchifyConcurrentHashMapObject = null;
public static void main(String[] args) throws InterruptedException {
// Test with Hashtable Object
crunchifyHashTableObject = new Hashtable<String, Integer>();
crunchifyPerformTest(crunchifyHashTableObject);
// Test with synchronizedMap Object
crunchifySynchronizedMapObject = Collections.synchronizedMap(new HashMap<String, Integer>());
crunchifyPerformTest(crunchifySynchronizedMapObject);
// Test with ConcurrentHashMap Object
crunchifyConcurrentHashMapObject = new ConcurrentHashMap<String, Integer>();
crunchifyPerformTest(crunchifyConcurrentHashMapObject);
}
public static void crunchifyPerformTest(final Map<String, Integer> crunchifyThreads) throws InterruptedException {
System.out.println("Test started for: " + crunchifyThreads.getClass());
long averageTime = 0;
for (int i = 0; i < 5; i++) {
long startTime = System.nanoTime();
ExecutorService crunchifyExServer = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
for (int j = 0; j < THREAD_POOL_SIZE; j++) {
crunchifyExServer.execute(new Runnable() {
#SuppressWarnings("unused")
#Override
public void run() {
for (int i = 0; i < 500000; i++) {
Integer crunchifyRandomNumber = (int) Math.ceil(Math.random() * 550000);
// Retrieve value. We are not using it anywhere
Integer crunchifyValue = crunchifyThreads.get(String.valueOf(crunchifyRandomNumber));
// Put value
crunchifyThreads.put(String.valueOf(crunchifyRandomNumber), crunchifyRandomNumber);
}
}
});
}
// Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation
// has no additional effect if already shut down.
// This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.
crunchifyExServer.shutdown();
// Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is
// interrupted, whichever happens first.
crunchifyExServer.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
long entTime = System.nanoTime();
long totalTime = (entTime - startTime) / 1000000L;
averageTime += totalTime;
System.out.println("500K entried added/retrieved in " + totalTime + " ms");
}
System.out.println("For " + crunchifyThreads.getClass() + " the average time is " + averageTime / 5 + " ms\n");
}
}
So in the crunchifyPerformTest class, he's starting an ExecutorService with 5 threads and then submitting 5 different runnables with 500k reads and writes to the hashmap each time? Will the executor service automatically have 5 threads executing each runnable?
No. Each Runnable is executed on exactly one thread. This means that all Runnables will be executed in parallel, because the number of Runnables matches the number of available threads.
You could also submit 6 Runnables. In this case 5 of them would be executed in parallel and as soon as one Runnable has finished execution, the sixth one will be executed.
By the way, I think the docs are quite clear about the behaviour
of this ExecutorService.
I'm having big troubles understanding the Java ThreadPoolExecutor. For example, I want to calculate the squares of numbers 1-1000:
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<ArrayList<Integer>> c = new squareCalculator(1000);
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<ArrayList<Integer>> result = executor.submit(c);
for(Integer i: result.get()){
System.out.println(i);
}
}
And the
public class squareCalculator implements Callable<ArrayList<Integer>>{
private int i;
private int max;
private int threadID;
private static int id;
private ArrayList<Integer> squares;
public squareCalculator(int max){
this.max = max;
this.i = 1;
this.threadID = id;
id++;
squares = new ArrayList<Integer>();
}
public ArrayList<Integer> call() throws Exception {
while(i <= max){
squares.add(i*i);
System.out.println("Proccessed number " +i + " in thread "+this.threadID);
Thread.sleep(1);
i++;
}
return squares;
}
}
Now my problem is, that I only get one thread doing the calculations. I expected to get 5 threads.
If you want the Callable to run 5 times concurrently, you need to submit it 5 times.
You only submitted it once, and then ask for its result 5 times.
Javadoc of submit():
Submits a value-returning task for execution and returns a
Future representing the pending results of the task. The
Future's get method will return the task's result upon
successful completion.
You see that Javadoc for submit() uses the singular for "task", not "tasks".
The fix is easy: submit it multiple times:
Future<ArrayList<Integer>> result1 = executor.submit(c);
Future<ArrayList<Integer>> result2 = executor.submit(c);
Future<ArrayList<Integer>> result3 = executor.submit(c);
/// etc..
result1.get();
result2.get();
result3.get();
// etc..
The ExecutorService will use one thread to execute each Callable task that you submit. Therefore, if you want to have multiple threads calculating the squares, you have to submit multiple tasks, for example one task for each number. You would then get a Future<Integer> from each task, which you can store in a list and call get() on each one to get the results.
public class SquareCalculator implements Callable<Integer> {
private final int i;
public SquareCalculator(int i) {
this.i = i;
}
#Override
public Integer call() throws Exception {
System.out.println("Processing number " + i + " in thread " + Thread.currentThread().getName());
return i * i;
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<Integer>> futures = new ArrayList<>();
// Create a Callable for each number, submit it to the ExecutorService and store the Future
for (int i = 1; i <= 1000; i++) {
Callable<Integer> c = new SquareCalculator(i);
Future<Integer> future = executor.submit(c);
futures.add(future);
}
// Wait for the result of each Future
for (Future<Integer> future : futures) {
System.out.println(future.get());
}
executor.shutdown();
}
}
The output then looks something like this:
Processing number 2 in thread pool-1-thread-2
Processing number 1 in thread pool-1-thread-1
Processing number 6 in thread pool-1-thread-1
Processing number 7 in thread pool-1-thread-2
Processing number 8 in thread pool-1-thread-2
Processing number 9 in thread pool-1-thread-2
...
1
4
9
...
This is a funny problem to try to do in parallel because creating the result array (or list) runs in O(n) time because it gets initialized with zeros on creation.
public static void main(String[] args) throws InterruptedException {
final int chunks = Runtime.getRuntime().availableProcessors();
final int max = 1001;
ExecutorService executor = Executors.newFixedThreadPool(chunks);
final List<ArrayList<Long>> results = new ArrayList<>(chunks);
for (int i = 0; i < chunks; i++) {
final int start = i * max / chunks;
final int end = (i + 1) * max / chunks;
final ArrayList<Long> localResults = new ArrayList<>(0);
results.add(localResults);
executor.submit(new Runnable() {
#Override
public void run() {
// Reallocate enough space locally so it's done in parallel.
localResults.ensureCapacity(end - start);
for (int j = start; j < end; j++) {
localResults.add((long)j * (long)j);
}
}
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MICROSECONDS);
int i = 0;
for (List<Long> list : results) {
for (Long l : list) {
System.out.printf("%d: %d\n", i, l);
++i;
}
}
}
Overhead dealing with the wrapper classes will kill performance, here, so you should use something like Fastutil. Then, you could join them with something like Guava's Iterables.concat, only a List version that's compatible with Fastutil's LongList.
This might also make a good ForkJoinTask, but again, you'll need efficient logical (mapping, not copying; the reverse of List.sublist) List concatenation functions to realize a speedup.
I'm currently in the process of learning Java concurrency. And I am very surprised by the way following code behaves.
import java.util.concurrent.*;
public class Exercise {
static int counter = 0;
static synchronized int getAndIncrement() {
return counter++;
}
static class Improper implements Runnable {
#Override
public void run() {
for (int i = 0; i < 300; i++) {
getAndIncrement();
}
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 300; i++) {
executorService.submit(new Improper());
}
executorService.shutdown();
System.out.println(counter);
}
}
Shouldn't it output 90000 all the time? Instead the result differs all the time.
executorService.shutdown() doesn't wait for the service to shut down. You need a call to awaitTermination.
you access the counter from the main method without locking. I think you would narrowly escape a data race if you waited for the executor service to shut down, but be warned that, in general, you must synchronize on all accesses of a shared variable, not just writes, to have any visibility guarantees from the Java Memory Model.
You need to make sure that all tasks have had time to terminate. Use awaitTermination
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 300; i++) {
executorService.submit(new Improper());
}
executorService.shutdown();
executorService.awaitTermination(2, TimeUnit.SECONDS);
System.out.println(counter);
}
You don't wait for all your submited tasks to terminate, see the javadoc for ExecutorService.html#shutdown. So gettting an arbitrary output each time is the expected behabiour.
what I need to do is be able to stop all threads running from one thread class that implements runnable. This is what I mean: here is the beginning of my "thread" class:
public class HTTP extends Thread
{
int threadNumber;
String host;
int port;
int timeLeft;
private BufferedReader LocalBufferedReader;
public HTTP(int threadNumber, String host, int port, int timeLeft)
{
this.threadNumber = threadNumber;
this.host= host;
this.port = port;
this.timeLeft = (timeLeft * 1000);
}
public void run()
{
This is how I am creating the multiple threads to do this:
for (int n = 1; n <= m; n++) {
new HTTP(n + 1, str, j, k).start();
}
m is the number of threads to create. This can be anywhere from 50-1000. Now what I need to do is just abruptly stop all of them at once. How can I do that?
First store all the threads:
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int n = 1; n <= m; n++) {
Thread t = new HTTP(n + 1, str, j, k);
threads.add(t);
t.start();
}
Now for stop method, just loop all the threads and call interrupt on them:
for(Thread thread : threads)
{
thread.interrupt();
}
Make sure to check isIntruppted() in your HTTP threads. So you would do something like this:
public class InterruptTest {
static class TThread extends Thread {
public void run() {
while(!isInterrupted()) {
System.out.println("Do Work!!!");
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = new TThread();
t.start();
Thread.sleep(4000);
System.out.println("Sending interrupt!!");
t.interrupt();
Thread.sleep(4000);
}
}
Stopping threads in Java is a cooperative process implemented with interruptions. You could store your threads and interrupt them one by one:
List<Thread> threads = new ArrayList<> ();
for (int n = 1; n <= m; n++) {
Thread t = new HTTP(n + 1, str, j, k);
threads.add(t);
t.start();
}
//later on
for (Thread t : threads) {
t.interrupt();
}
However, it is worth noting a few things:
this will only work if your run method reacts to interruption by stopping what it is doing
you could do the same thing more easily with a thread pool, for example by using one of the ExecutorService returned by the various factory methods provided by the Executors class. They would indeed handle the lifecycle of threads for you.
Firstly, starting 1000 threads is practically pointless as few of them will be scheduled to actually run concurrently.
Secondly, you can't "stop" threads. All you can do is ask them nicely via cooperative code to stop.
The easiest way to do what you want is to shutdown the JVM.