How to stop a thread after it has completed the runnable? - java

I have a list of tasks and a limited number of threads. The goal is to time how long the tasks take to finish using this number of threads.
I know something is wrong with the way I am using threads and Runnable object. I am new to them and can't seem to figure out how to fix it.
It errors with a java.lang.OutOfMemoryError: Java heap space error on the line worker.start() after a few seconds.
Here is my code:
public class Tasks {
static Timer timer; //times how long it takes to complete all tasks
public static void main(String[] args) {
Job t1 = new Sleep(5);
Job t2 = new Sum(1000);
Job t3 = new Sleep(3);
Job t4 = new Sleep(10);
Job t5 = new Sum(10);
Graph g = new Graph(5);
g.getNumEdges();
g.addEdge(t1, t2);
g.addEdge(t2, t3);
g.addEdge(t2, t4);
g.addEdge(t3, t5);
g.addEdge(t4, t5);
//System.out.println(t5.getPredecessor());
System.out.println(parseGraph(g, 2));
}
public static String parseGraph(Graph graph, int K)
{
long startTime = System.nanoTime();//start timer
int numThreads = K;
ArrayList<Job> x = graph.getNodes();
//check for cycles
CycleFinder dc = new CycleFinder(graph);
if(dc.hasCycle()==true)
{
System.out.println(dc.cycle());
return ("The graph has cycles and could not be parsed through.");
}
List<Thread> threads = new ArrayList<Thread>();
ArrayList<Job> ready = new ArrayList<Job>();
while (x.isEmpty()!= true)
{
for(int i=0; i<x.size(); i++)
{
Job y= x.get(i);
System.out.println(y);
if(y.getComplete()== true)
{
ready.remove(y);
graph.removeNode(y);
x.remove(y);
}
if(y.getPredecessor().isEmpty() || y.getPredecessor() ==null)
ready.add(y);
}
for (int i = 0; i < numThreads && i < ready.size(); i++) {
System.out.println("test");
Runnable task = new MyRunnable(ready.get(i));
Thread worker = new Thread(task);
worker.setName(String.valueOf(i));
worker.start();
threads.add(worker);
}
//int running = 0;
//do {
//running = 0;
//for (Thread thread : threads) {
//if (thread.isAlive()) {
// running++;
// }
// }System.out.println("We have " + running + " running threads. ");
// } while (running > 0);
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
return ("The Tasks took " + (duration/1000) + " seconds");
}
}

You don't need to.. After thread has completed the run() method of Runnable, it should be completed.
The OOM error you are facing is something to do with the logic inside the run() method of the Runnable.

Related

Inline Thread objects runs much faster than class that inherits from Thread

Here is a main that runs a simple counting loop three ways:
Single-threaded
2 threads using inline code that creates two distinct Thread objects
2 threads using instances of the CountingThread class that inherits from Thread
package main;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
demo();
}
public static void demo() {
final long limit = 100_000_000_000L;
long startTime = System.currenatTimeMillis();
for (long i = 0; i < limit; i++) {
// Nothing to see here, just counting
}
long endTime = System.currentTimeMillis();
System.out.println("Single threaded: Total execution time: " + (endTime - startTime) + " milliseconds.");
// Now try it in two threads. Each thread will perform 1/2 of the counting
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (long i = 0; i < limit/2; i++) {
// Nothing to see here, just counting
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (long i = limit/2; i < limit; i++) {
// Nothing to see here, just counting
}
}
});
startTime = System.currentTimeMillis();
t1.start();
t2.start();
// Join t1 until it ends, then join t2 until it ends. Note that t1 and t2 are running in parallel with this thread.
try {t1.join();} catch (InterruptedException e) {}
try {t2.join();} catch (InterruptedException e) {}
endTime = System.currentTimeMillis();
System.out.println("2 threaded using inline code: Total execution time: " + (endTime - startTime) + " milliseconds.");
// Now try it with 2 instances of the CountingThread class.
ArrayList<CountingThread> countingThreads = new ArrayList<CountingThread>();
int numberOfThreads = 2;
long increment = limit / numberOfThreads;
for (int i = 0; i < numberOfThreads; i++) {
long start, end;
start = i * increment;
end = start + increment;
countingThreads.add(new CountingThread(start, end));
}
// Launch all the threads to run in parallel
startTime = System.currentTimeMillis();
for (int i = 0; i < numberOfThreads; i++) {
countingThreads.get(i).run();
}
// Wait for all the threads to finish
for (int i = 0; i < numberOfThreads; i++) {
try {countingThreads.get(i).join();} catch(InterruptedException ex) {}
}
endTime = System.currentTimeMillis();
System.out.println(numberOfThreads + " threaded using classes: Total execution time: " + (endTime - startTime) + " milliseconds.");
}
}
Here is the class that inherits from Thread:
package main;
/**
* Count from one long int up to another long int. Really simple
*
*/
public class CountingThread extends Thread {
private long start, end;
public CountingThread(long start, long end) {
this.start = start;
this.end = end;
}
#Override
public void run() {
for(long i = start; i <= end; i++) {
}
// System.out.println("Thread counted from " + start + " to " + end);
}
}
Here is the output:
Single threaded: Total execution time: 40379 milliseconds.
2 threaded using inline code: Total execution time: 23312 milliseconds.
2 threaded using classes: Total execution time: 40358 milliseconds.
It seems like methods 2 and 3 should take about the same amount of time. What's up with that?
The machine has 4 cores.
You made a mistake and call #run instead of #start. Run method is executed in the same thread.
countingThreads.get(i).run();

How can I schedule some work in n threads separately

Lets say I have n threads concurrently taking values from a shared queue:
public class WorkerThread implements Runnable{
private BlockingQueue queue;
private ArrayList<Integer> counts = new ArrayList<>();
private int count=0;
public void run(){
while(true) {
queue.pop();
count++;
}
}
}
Then for each thread, I want to count every 5 seconds how many items it has dequeued, and then store it in its own list (counts)
I've seen here Print "hello world" every X seconds how you can run some code every x seconds:
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
counts.add(count);
count = 0
}
}, 0, 5000);
The problem with this is that I can't access count variable and the list of counts unless they are static. But I don't want them to be static because I don't want the different threads to share those variables.
Any ideas of how to handle this?
I don't think it's possible to use scheduled execution for you case(neither Timer nor ScheduledExecutorService), because each new scheduled invocation will create a new tasks with while loop. So number of tasks will increase constantly.
If you don't need to access this list of counts in runtime i would suggest something like this one:
static class Task implements Runnable {
private final ThreadLocal<List<Integer>> counts = ThreadLocal.withInitial(ArrayList::new);
private volatile List<Integer> result = new ArrayList<>();
private BlockingQueue<Object> queue;
public Task(BlockingQueue<Object> queue) {
this.queue = queue;
}
#Override
public void run() {
int count = 0;
long start = System.nanoTime();
try {
while (!Thread.currentThread().isInterrupted()) {
queue.take();
count++;
long end = System.nanoTime();
if ((end - start) >= TimeUnit.SECONDS.toNanos(1)) {
counts.get().add(count);
count = 0;
start = end;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// the last value
counts.get().add(count);
// copy the result cause it's not possible
// to access thread local variable outside of this thread
result = counts.get();
}
public List<Integer> getCounts() {
return result;
}
}
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(3);
BlockingQueue<Object> blockingQueue = new LinkedBlockingQueue<>();
Task t1 = new Task(blockingQueue);
Task t2 = new Task(blockingQueue);
Task t3 = new Task(blockingQueue);
executorService.submit(t1);
executorService.submit(t2);
executorService.submit(t3);
for (int i = 0; i < 50; i++) {
blockingQueue.add(new Object());
Thread.sleep(100);
}
// unlike shutdown() interrupts running threads
executorService.shutdownNow();
executorService.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("t1 " + t1.getCounts());
System.out.println("t2 " + t2.getCounts());
System.out.println("t3 " + t3.getCounts());
int total = Stream.concat(Stream.concat(t1.getCounts().stream(), t2.getCounts().stream()), t3.getCounts().stream())
.reduce(0, (a, b) -> a + b);
// 50 as expected
System.out.println(total);
}
Why not a static AtomicLong?
Or the WorkerThread(s) can publish that they poped to the TimerTask or somewhere else? And the TimerTask reads that info?

start multiple threads at the same time

For our assignment for class, we have to count the amount of words in a txt file by splitting it into n segments, which we are supposed to be able to set before launching the programm. Each segment should then get its own thread, which counts the words and then stops. At the end, the main thread should collect all the individual word counts and add them together.
This is (part of) what I wrote so far
for (int i = 0; i < segments; i++){
Thread thread = new Thread();
thread.start();
int words = counting(stringarray[i]);
totalwords += words;
long nanos = ManagementFactory.getThreadMXBean().getThreadCpuTime(Thread.currentThread().getId());
System.out.println("This Thread read " + words + " words. The total word count now is " + totalwords +
". The time it took to finish for this thread is " + nanos +".");
System.out.println("Number of active threads from the given thread: " + Thread.activeCount());
}
Now, while this gets the primary job done (counting the words in different threads and adding them to the total), I dont know how to just "leave the thread be" and then add the individual wordcounts together after every thread has done its job.
Additionally, while this is definitely starting multiple threads, it only ever prints out that I have 2, or maybe 3 threads running at a time, even if I split the txt into 100 segments. Is there a way to have them all run at the same time?
The wording of the question suggest that each thread has its own counter, so I would declare a thread class:
public class WordCounter extends Thread {
private String text;
private int count;
public WordCounter(String text) {
this.text = text;
}
public int getCount() {
return count;
}
#Override
public void run() {
count = counting(text);
}
}
and use it as follows:
WordCounter[] threads = new WordCounter[segments];
for (int i = 0; i < segments; ++i) {
threads[i] = new WordCounter(stringarray[i]);
threads[i].start();
}
int total = 0;
for (int i = 0; i < segments; ++i) {
threads[i].join();
total += threads[i].getCount();
}
You may use next code snippet as a basis.
Note, that in case you increment common variable in different threads, this operation has to be thread-safe. That's why AtomicInteger variable is used as a counter
final List<String> segments = new ArrayList<>();
//TODO:Fill segments ... this is up to you
//In case threads will increment same variable it has to be thread-safe
final AtomicInteger worldCount = new AtomicInteger();
//Create Thread for each segment (this is definitely not optimal)
List<Thread> workers = new ArrayList<>(segments.size());
for (int i = 0; i < segments.size(); i++) {
final String segment = segments.get(i);
Thread worker = new Thread(new Runnable() {
#Override
public void run() {
//increment worldCount
worldCount.addAndGet(counting(segment));
}
});
workers.add(worker);
worker.start();
}
//Wait until all Threads are finished
for (Thread worker : workers) {
worker.join();
}
int result = worldCount.get();
Same solutions, but with Executors:
final List<String> segments = new ArrayList<>();
segments.add("seg1");
segments.add("seg2");
segments.add("seg 3");
final AtomicInteger worldCount = new AtomicInteger();
List<Future> workers = new ArrayList<>(segments.size());
ExecutorService executor = Executors.newFixedThreadPool(segments.size());
for (String segment : segments) {
Future<Integer> worker = executor.submit(() -> worldCount.addAndGet(counting(segment)));
workers.add(worker);
}
executor.shutdown();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("Still waiting...");
System.exit(0);
}
int result = worldCount.get();
System.out.println("result = " + result);

how to run the main thread after all child threads have completed there exceution

I have a requirement in which 28 threads have to complete some functionality. I have created these threads as in anonymous inner classes like :
Thread t=new Thread(new Runnable(){public void run()
{//code
}}
);
t.start();
Now I want that the further execution should start after all these threads have finished there work.
Note : I am confused about join() method as it makes my threads run sequentially.
So can anyone suggest me how can I make main thread run once these threads are done with work.
Note : I am confused about join() method as it makes my threads run sequentially.
It will do that if you have code like this:
for (Runnable runnable : runnables) {
Thread t = new Thread(runnable);
t.start();
t.join();
}
However, you can start all the threads you want to run in parallel, then call join on them all. For example:
List<Thread> threads = new ArrayList<>();
for (Runnable runnable : runnables) {
Thread t = new Thread(runnable);
t.start();
threads.add(t);
}
// Now everything's running - join all the threads
for (Thread thread : threads) {
thread.join();
}
// Now you can do whatever you need to after all the
// threads have finished.
There are many other approaches, of course - starting threads directly may well not be as suitable in your code as using a higher level abstraction; it depends on what you're trying to achieve. The above should work fine though - assuming all the Runnables are able to run in parallel without blocking each other through synchronization.
Make use of CountDownLatch.
public static void main(String... args) {
final CountDownLatch latch = new CountDownLatch(28);
for(int i=0;i<28;i++) {
Thread t=new Thread(new Runnable(){
public void run()
{
try {
//code
} finally {
latch.countDown();
}
}
});
t.start();
}
latch.await();
// Continue Code
}
Use a CountDownLatch and wait for all your threads to complete. :) .
PS : I gotto agree, using join() is also correct and more efficient.
example code :
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("t1 : " + i);
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("t2 : " + i);
}
}
});
t2.start();
t1.join();
t2.join();
System.out.println("main");
}
O/P :
t1 : 0
t1 : 1
t2 : 0
t1 : 2
t1 : 3
t2 : 1
t1 : 4
t1 : 5
t2 : 2
t1 : 6
t1 : 7
t2 : 3
t1 : 8
t1 : 9
t2 : 4
t2 : 5
t2 : 6
t2 : 7
t2 : 8
t2 : 9
main
According to the behaviour you're giving for join, I'm guessing you're starting and joining the threads within a single loop.
If you check the javadoc on this page, you'll note that a call to join will halt the execution of the calling thread until the other thread has finished executing.
You might want to keep an array or a list of threads when creating them, and starting them all in one loop, and only then joining them all.
Thread[] workers = new Thread[28];
for (int i = 0; i < workers.length; i++) {
workers[i] = new Thread { ... };
}
// Start running all threads
for (Thread worker: workers) {
worker.start();
}
// Make sure all threads are completed
for (Thread worker: workers) {
worker.join(); // if the worker already stopped, it'll return immediately.
}
// Now all threads have finished running and you can start post-processing
It's not the most elegant solution, but it'll do the trick.
As mentioned by others, you should probably use a CountDownLatch (haven't used one yet, so I can't provide feedback)
Edit: I've been beaten to it by Jon Skeet, sorry for the redundant answer...
CountDownLatch is better option.
I have created dummy program.
In this program I am sum 1000 number. I created 10 thread. In main thread I am doing dome of all child thread sum. you will get understand to simply viewing the code.
package Test1;
import java.util.concurrent.CountDownLatch;
class Sum extends Thread {
private int from;
private int to;
private int sum = 0;
CountDownLatch latch;
public int getSum() {
return sum;
}
public Sum(int from, int to, CountDownLatch latch) {
this.from = from;
this.to = to;
this.latch = latch;
}
public void run() {
for (int i = from; i < to; i++) {
sum += i;
}
latch.countDown();
}
}
public class Test5 {
public static void main(String[] args) throws InterruptedException {
int n = 1000;
int tn = 10;
int from = 1;
int to;
int sum = 0;
Sum[] sumArray = new Sum[tn];
final CountDownLatch latch = new CountDownLatch(tn);
for (int i = 0; i < tn; i++) {
to = from + n / tn;
Sum s = new Sum(from, to, latch);
sumArray[i] = s;
s.start();
from = to;
}
// Thread.sleep(1000);
latch.await();
for (int i = 0; i < tn; i++) {
sum += sumArray[i].getSum();
}
System.out.println(sum);
}
}

Ending threads in java correctly

I have a problem with Threads in Java.
I would like to write a program where there is Class Main which has ArrayList of Threads of some class (Class Task) which just writes a letter and the number. Object Main just wakes one Thread from ArrayList and let it to do something while the same object(Main) sleeps another one.
But there is one problem even if I change the Main.ACTIVE to false it does not end all of the Threads some stay on, and it's random, I just would like to make them end and write:
I am saying goodbay + character - sth like that
public class Main extends Thread {
ArrayList<Thread> threads;
static boolean ACTIVE = true;
public Main() {
super();
threads = new ArrayList<Thread>();
}
public void run(){
Object monitor = new Object();
for (int i = 0; i <= 5; i++) {
threads.add(new Thread(new Task(i + 65, monitor)));
}
long cT = System.currentTimeMillis();
for (int i = 0; i < threads.size(); i++) {
threads.get(i).start();
}
System.out.println("BEFORE synchronized(monitor)");
synchronized(monitor){
while (System.currentTimeMillis() - cT < 1000) {
try{
monitor.notify();
Thread.sleep(50);
monitor.wait();
} catch(Exception e){
e.printStackTrace();}
}
System.out.println("BEFORE ACTIVE= FALSE and after WHILE in Main");
ACTIVE = false;
for(int i = 0; i < threads.size(); i++){
System.out.println(threads.get(i).getState());
}
}
System.out.println("LAST COMMAND IN MAIN");
}
}
public static void main(String[] args) {
new Main().start();
//new Thread(new Task(65)).start();
}
}
And the Task Class
public class Task implements Runnable {
int nr;
char character;
Object monitor;
public Task(int literaASCII, Object monitor) {
this.nr = 0;
this.monitor = monitor;
character = (char) (literaASCII);
}
#Override
public void run() {
synchronized (monitor) {
while (Main.ACTIVE) {
try {
System.out.println("ENTERING WHILE IN TASK");
monitor.wait();
System.out.print(nr + "" + character + ", ");
nr++;
int r = (int) ((Math.random() * 50) + 50); // <500ms,1000ms)
Thread.sleep(r);
} catch (Exception e) {e.printStackTrace();}
monitor.notify();
System.out.println("YYYYYYYYY");
}
System.out.println("AFTER WHILE IN Task");
}
System.out.println("I am saying goodbye " + character);
}
}
I would recommend that you look at the more modern concurrency classes in java.util.concurrent package, especially ExecutorService. And read "Java Concurrency In Practice."
Your problem is for starters that ACTIVE should be marked as volatile. Any variable that is shared by multiple threads needs to somehow be synchronized or marked as volatile so that it will have a memory barrier around its reading and writing.
Another thing you can do from a boolean standpoint is to use the AtomicBoolean class instead of a volatile boolean.
Instead of a static volatile boolean, you might instead consider to have a volatile boolean for each Task object so that Main has more fine grained control over the individual tasks and you are using a static "global" variable. You could even add a task.shutdown() method to set the active flag.
Lastly, as #duffmo mentioned, you should always consider using one of the thread-pools ExecutorService if you always just want to have one thread running. Something like Executors.newFixedThreadPool(1). But I can't quite tell if you only want one thread all of the time. If you used an ExecutorService then main would just do:
ExecutorService threadPool = Executors.newFixedThreadPool(1);
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i <= 5; i++) {
// the monitor would not be needed
threadPool.submit(new Task(i + 65));
}
threadPool.shutdown();
for (Future future : futures) {
// this waits for the working task to finish
future.get();
}
But if you need your background task to stop and start like it is currently doing with the monitor then this model might not work.
Now naswer is
0A, 0B, 0C, 0D, 0E, 0F, 1A, 1B, 1C, 1D, 1E, 1F, WAITING
WAITING
WAITING
WAITING
WAITING
WAITING
LAST COMMAND IN MAIN
I added sleep after starting threads
import java.util.ArrayList;
public class Main extends Thread {
ArrayList<Thread> threads;
volatile static boolean ACTIVE = true;
public Main() {
super();
threads = new ArrayList<Thread>();
}
public void run(){
Object monitor = new Object();
for (int i = 0; i <= 5; i++) {
threads.add(new Thread(new Task(i + 65, monitor)));
}
long cT = System.currentTimeMillis();
for (int i = 0; i < threads.size(); i++) {
threads.get(i).start();
}
try{Thread.sleep(50);}catch(Exception e){e.printStackTrace();}
// System.out.println("BEFORE synchronized(monitor)");
synchronized(monitor){
while (System.currentTimeMillis() - cT < 1000) {
try{
monitor.notify();
Thread.sleep(500);
monitor.wait();}catch(Exception e){e.printStackTrace();}
}
// System.out.println("BEFORE ACTIVE= FALSE and after WHILE in Main");
ACTIVE = false;
for(int i = 0; i < threads.size(); i++){
System.out.println(threads.get(i).getState());
}
}
System.out.println("LAST COMMAND IN MAIN");
}
public static void main(String[] args) {
new Main().start();
//new Thread(new Task(65)).start();
}
}
and the TASK
public class Task implements Runnable {
int nr;
char character;
Object monitor;
public Task(int literaASCII, Object monitor) {
this.nr = 0;
this.monitor = monitor;
character = (char) (literaASCII);
}
#Override
public void run() {
synchronized (monitor) {
while (Main.ACTIVE) {
try {
// System.out.println("ENTERING WHILE IN TASK");
monitor.wait();
System.out.print(nr + "" + character + ", ");
nr++;
int r = (int) ((Math.random() * 50) + 50); // <500ms,1000ms)
Thread.sleep(r);
} catch (Exception e) {e.printStackTrace();}
monitor.notify();
// System.out.println("YYYYYYYYY");
}
System.out.println("AFTER WHILE IN Task");
}
System.out.println("I am saying goodbye " + character);
}
}

Categories