My code is working fine if it is the following way.
Scanner input = new Scanner(System.in);
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 3; i++)
{
Runnable worker = new ClassA();
executor.execute(worker);
}
Instead, I want to run continuously in while(true) loop and break the loop when user enters 1. I tried the following way but it is not working. it is not running continously but stopping (blocking) at this line int stop = input.nextInt(); Can anyone please tell me where the mistake is. Whether it is the correct way of doing or not if not please suggest an alternative. My code in Class A connects to jms queue and should continuously read messages from queue.
Scanner input = new Scanner(System.in);
ExecutorService executor = Executors.newFixedThreadPool(2);
while(true)
{
Runnable worker = new ClassA();
executor.execute(worker);
int stop = input.nextInt();
if(stop == 1) {
break;
}
}
EDIT: The following is the edited code. when scanner.nextInt() value is entered 1, finished = true. While(!finished) loop is break, code in it is not executing but still my Consumer class is running continuously.
public class ScannerProblem {
public static boolean finished = false;
static class Listener implements Runnable {
Scanner scanner = new Scanner(System.in);
#Override
public void run() {
while (true) {
System.out.println("scanning");
if (scanner.nextInt() == 1) {
System.out.println("scanning finished");
finished = true;
return;
} else {
System.out.println("scanned something strange");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable {
javax.jms.Connection jmsConnection = null;
private static ProcessRequest processRequest = new ProcessRequest();
#Override
public void run() {
ActiveMQConnection con = new ActiveMQConnection();
jmsConnection = con.openTcpConnection();
try {
String json = null;
Session session = jmsConnection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("Upload_Queue");
MessageConsumer consumer = session.createConsumer(queue);
TextMessage message = (TextMessage) consumer.receive();
System.out.println("Message #" + ": " + message.getText());
json = message.getText();
processRequest.upload(json);
System.out.println("Thread ID: " + Thread.currentThread().getId());
if (jmsConnection != null) {
jmsConnection.close();
}
Thread.sleep(5000);
}
catch(JMSException e) {
e.printStackTrace();
}
catch(InterruptedException e){
e.printStackTrace();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(new Listener());
while (!finished) {
System.out.println("finished::"+finished);
pool.submit(new Consumer());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
int stop = input.nextInt() is a blocking call, so it execute ClassA runnable only once then wait for input.
You need to move input code to another thread so it's not blocking the executions of ClassA.
Maybe a better option would be to have only one execution of ClassA and have another while(true) loop inside it.
Related
I've been trying to make a simple implementation of Thread-Pool using Active Objects.
Here is my Main:
public static void main(String[] args){
MyThreadPool tp = new MyThreadPool(100,3);
tp.execute(()->{
try { Thread.sleep(5*1000); } catch (InterruptedException e) {}
System.out.println("42");
});
tp.shutDown();
}
The shutDown method is usually called first through the Main and therefore keeps the Active Objects "alive" unwantedly, but sometimes I get the wanted outcome.
Any idea why there is uncertainty about the result?
Below you can see the rest of the classes:
public class MyThreadPool {
ArrayBlockingQueue<Runnable> q;
ArrayBlockingQueue<ActiveObject> activeObjects;
volatile boolean stop;
AtomicInteger count;
Thread t;
Runnable stopTask;
public MyThreadPool(int capacity, int maxThreads) {
activeObjects = new ArrayBlockingQueue<>(maxThreads);
q = new ArrayBlockingQueue<>(capacity);
count = new AtomicInteger(0);
stopTask = ()->stop = true;
t=new Thread(()->{
//System.out.println("Thread-Pool Started");
while(!stop){
//if queue is empty it is gonna be a blocking call
try {
Runnable task = q.take();
if(task==stopTask)
stopTask.run();
else
//size() is atomic integer
if (count.get() < maxThreads) {
ActiveObject a = new ActiveObject(capacity);
activeObjects.put(a);
count.incrementAndGet();
a.execute(task);
}
//we will assign the next task to the least busy ActiveObject
else {
int minSize = Integer.MAX_VALUE;
ActiveObject choice = null;
for (ActiveObject a : activeObjects) {
if (a.size() < minSize) {
minSize = a.size();
choice = a;
}
}
choice.execute(task);
}
} catch (InterruptedException e) { }
}
//System.out.println("Thread-Pool Ended");
});
t.start();
}
//execute returns right away - just puts into the queue
public void execute(Runnable r ){
// if capacity is full it is gonna be a blocking call
if(!stop)
try { q.put(r); } catch (InterruptedException e) { }
}
public void shutDownNow(){
activeObjects.forEach(a->a.shutDownNow());
stop = true;
t.interrupt();
}
public void shutDown(){
activeObjects.forEach(a->a.shutDown());
execute(stopTask);
}
public class ActiveObject {
ArrayBlockingQueue<Runnable> q;
volatile boolean stop;
Thread t;
public ActiveObject(int capacity) {
q = new ArrayBlockingQueue<>(capacity);
t=new Thread(()->{
//System.out.println("Active Object Started");
while(!stop){
//if queue is empty it is gonna be a blocking call
try {
q.take().run();
} catch (InterruptedException e) { }
}
//System.out.println("Active Object Ended");
});
t.start();
}
//execute returns right away - just puts into the queue
public void execute(Runnable r ){
// if capacity is full it is gonna be a blocking call
if(!stop)
try { q.put(r); } catch (InterruptedException e) { }
}
public void shutDownNow(){
stop = true;
t.interrupt();
}
public void shutDown(){
execute(()->stop=true);
}
public int size(){
return q.size();
}
}
In your main method you create a thread pool (which also creates and starts tp.t thread), enqueue a task into tp.q, and then call tp.shutDown():
MyThreadPool tp = new MyThreadPool(100, 3);
tp.execute(() -> {...});
tp.shutDown();
Imagine that tp.shutDown() in the main thread is executed before the MyThreadPool.t thread processes the enqueued task:
activeObjects.forEach(a -> a.shutDown());
execute(stopTask);
here activeObjects is empty, you enqueue stopTask into tp.q, and main thread finishes.
Now we only have MyThreadPool.t thread, let's see what it does:
while (!stop) {
try {
Runnable task = q.take();
if (task == stopTask)
stopTask.run();
else
if (count.get() < maxThreads) {
ActiveObject a = new ActiveObject(capacity);
activeObjects.put(a);
count.incrementAndGet();
a.execute(task);
}
else {
...
}
} catch (InterruptedException e) {
}
}
At this point q contains 2 tasks: a normal task and stopTask.
In the first loop iteration the normal task is taken from q, and is given for processing to a newly created ActiveObject:
ActiveObject a = new ActiveObject(capacity);
activeObjects.put(a);
count.incrementAndGet();
a.execute(task);
new ActiveObject() also creates and starts its own internal ActiveObject.t thread.
The second loop iteration processes stopTask:
if (task == stopTask)
stopTask.run();
which sets stop = true.
As a result, the next check while (!stop) returns false and MyThreadPool.t thread finishes.
Now we only have ActiveObject.t thread, which hasn't been stopped:
while (!stop) {
try {
q.take().run();
} catch (InterruptedException e) {
}
}
here the thread will keep waiting on q.take() forever.
I have the following class, I usually run about 10 threads of it
public class MyClass implements Runnable {
private volatile Device device = null;
public MyClass(Device device) {
this.device = device;
}
#Override
public void run() {
while (true) { // <--- I do know that the "true" has to be changed to a Boolean
try {
Worker worker = new Worker();
worker.work();
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
}
and in my main I start the threads like this
for (int i = 0; i < 2; i++) {
(new Thread(new MyClass())).start();
}
This is a console based program. What is the most reliable way to end the program? I think the best way would be to change while (true) to while (Boolean) and somehow change that Boolean for all threads, then when the loop ends, the program will end gracefully.
Here i'm ending it by waiting for a user input but you can change it to fire the stop method from anywhere
public static void main(String[] args) {
List<MyClass> myThreads = new ArrayList<>();
for (int i = 0; i < 2; i++) {
MyClass myClass = new MyClass();
Thread t = new Thread(myClass);
t.start();
myThreads.add(myClass);
}
Scanner in = new Scanner(System.in);
in.next();
for(MyClass t : myThreads){
t.stop();
}
}
class MyClass implements Runnable {
private Boolean flag;
public MyClass() {
this.flag = true;
}
#Override
public void run() {
while (flag) { // <--- I do know that the "true" has to be changed to a Boolean
try {
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
public void stop(){
this.flag = false;
} }
The easy way would be to store all your threads in a set and make loop joining them at the end.
Be aware that this is not the most ortodox neither the most efficient way to do this.
In your main:
HashSet<Thread> threads = new HashSet();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new MyClass());
threads.add(t);
t.start();
}
for (Thread thread: threads) {
thread.join();
}
some more material
The following code uses an executor service to fix the number of threads that run at any time, it provides a Future object that also tells you when your thread has shutdown gracefully. They share a shutdown object as well. This offers you a bit more flexibility as the executor service can let you decide how many threads run at any one time gracefully.
First lets created a shared shutdown object that will notify all the threads it is time to shut down. There will be one instance of this and each thread will have a copy.
public static class Shutdown {
private boolean running;
public void shutdown() {
this.running = false;
}
public boolean isRunning() {
return running;
}
}
Next let me just create a dummy thread that does nothing more than sleep forever while it is running. Obviously you can simply replace this with your own thread to do something useful.
public static class MyClass implements Runnable {
final Shutdown shutdown;
public MyClass(Shutdown shutdown) {
this.shutdown = shutdown;
}
#Override
public void run() {
while (shutdown.isRunning()) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("Did not gracefully shut down");
}
}
System.out.println("Thread in program ended!");
}
}
}
Now for the main class which will run everything, this is where the magic happens.
public class Main {
public static void main(String[] args) {
//run exactly 10 threads at a time
ExecutorService executorService = Executors.newFixedThreadPool(10);
//this is how we shut it down
Shutdown globalShutdown = new Shutdown();
//start up the 10 threads
List<Future<?>> futures = new ArrayList<>();
for(int i = 0; i< 10; i++)
futures.add(executorService.submit(new MyClass(globalShutdown)));
//gracefully shut them down
globalShutdown.shutdown();
try {
//wait for them all to shutdown
for(Future<?> future : futures)
future.get();
} catch (InterruptedException e) {
throw new IllegalStateException("This should never happen");
} catch (ExecutionException e) {
throw new IllegalStateException("This should never happen");
}
//everything got shutdown!
}
in practice however you probably also want to handle the case where your thread may not end gracefully due to a bug. Rather than stall forever you might want to add a timeout and if that timeout is exceeded then simply forcibly terminate all remaining threads. To do that replace the above try-catch block with this.
try {
//wait for them all to shutdown
boolean timedout = false;
for(Future<?> future : futures) {
if( !timedout ) {
try {
future.get(30, TimeUnit.SECONDS);
} catch (TimeoutException e) {
timedout = true;
}
}
if(timedout) {
future.cancel(true);
}
}
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("This should never happen");
}
This is a project I'm trying to do for University.
I'm making an app using sockets to connect several Clients to a Server.
When I get a new connection a new instance of ServerHandler is called that listens to the port for requests from the Client.
This is my ServerHandler class
public class ServerHandler implements Runnable {
private Socket clientSocket;
private Server server;
ArrayList<Thread> threads = new ArrayList<Thread>();
ArrayList<News> news = new ArrayList<News>();
ArrayList<News> filteredNews = new ArrayList<>();
private int iterator = 0;
private boolean available = true;
private boolean finished = false;
public ServerHandler(Socket clientSocket, Server server) {
this.clientSocket = clientSocket;
this.server = server;
this.news = server.getListNews();
}
#Override
public void run() {
System.out.println("Hello!");
while(true) {
try {
System.out.println("Waiting for input");
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String str = br.readLine();
System.out.println(str);
new Thread(new Runnable() {
#Override
public void run() {
try {
manageMessages();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void manageMessages() throws IOException, InterruptedException {
System.out.println("Button Search.");
launchThreads(str);
for(Thread t : threads) {
t.join();
}
filteredNews.sort(null);
System.out.println("News have been filtered and sorted.");
System.out.println("Sending info to Client.");
sendtoClient();
System.out.println("Sent info to Client.");
}
}).start();
} catch (IOException e) {
System.out.println("Socket closed" + e);
break;
}
}
}
When I get a request I launch a new Thread responsible of returning something to the Client.
My problem comes from the launchThreads(String str) method.
This method is meant to create and add 10 threads to an Array of Threads.
Each Thread then is going to run through the same ArrayList of News in search of a word (String str, sent by the Client).
All threads are supposed to share the work, that is searching for the String str through every single News in the shared ArrayList<News>.
private void launchThreads(String str) {
System.out.println("Lauching threads");
filteredNews.clear();
threads.clear();
finished = false;
available = true;
iterator = 0;
for(int i = 0; i < 10; i++) {
threads.add(new Thread(new Runnable(){public void run(){try {
queueThreads(str);
filterNews(str);
} catch (InterruptedException e) {
e.printStackTrace();
}}}));
threads.get(i).start();
}
System.out.println("Launched threads: " + threads.size());
}
private synchronized void queueThreads(String str) throws InterruptedException {
while(!available && !finished) {
System.out.println("Waiting.");
wait();
}
System.out.println("Gone through.");
available = false;
}
private synchronized void filterNews(String str) throws InterruptedException {
int contador = 0;
if(iterator < news.size()) {
String temp = news.get(iterator).getTitle() + " " + news.get(iterator).getBody();
String[] tempArray = temp.replaceAll("[^a-zA-Z ]", "").split("\\s+");
for(String word : tempArray) {
if(word.equalsIgnoreCase(str)) {
contador++;
}
}
if(contador > 0) {
News n = new News(news.get(iterator).getTitle(),news.get(iterator).getBody(), contador);
n.setTitle(contador + " - " + n.getTitle());
System.out.println(news.get(iterator).toString());
filteredNews.add(n);
}
iterator++;
}else {
finished = true;
}
available = true;
notifyAll();
queueThreads(str);}
What I'm getting is that only 1 Thread runs the whole search while the other ones just stay waiting until I change the finished flag to 'true', that is set when the search ends.
I would love to get some help on how can I launch several threads to run through the array sharing work between them.
Thanks in advance.
Hi I have been trying to solve the producer consumer problem in java without semaphores. When I use single producer and single consumer then my code is working fine. But when I add more than one consumer then it is completely messing up, all the consumer threads are going into the synchronized block. I'm not sure why this is happening. Here is my code :
Producer class:
public class Producer implements Runnable {
Object SharedObject = null;
String producerName= null;
Random rn = new Random();
public Producer(Main m, String s) {
this.SharedObject = m;
this.producerName=s;
}
public Producer(Main m) {
this.SharedObject = m;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == Main.bufferSize) {
try {
System.out.println("Producer is sleeping and waiting for notification form Consumer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount++;
System.out.println(this.producerName+" Produced the item and the item count is : " + Main.itemCount);
if (Main.itemCount == 1) {
SharedObject.notify();
System.out.println("Producer Notified the cosumer to wake up");
}
}
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer Class:
public class Consumer implements Runnable {
Object SharedObject = null;
String consumerName= null;
Random rn = new Random();
public Consumer(Main m, String s) {
SharedObject = m;
this.consumerName=s;
}
Consumer c= new Consumer((Main) SharedObject,consumerName);
synchronized void consume(){
synchronized (SharedObject) {
if (Main.itemCount == 0) {
try {
System.out.println(this.consumerName+" is sleeping and waiting for notify from Producer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount--;
System.out.println(this.consumerName+" consumed 1 item and the item Count is " + Main.itemCount);
if (Main.itemCount == 4) {
SharedObject.notifyAll();
System.out.println("Consumer notified the producer to wake up");
}
}
}
public void run() {
while (true) {
c.consume();
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class:
public class Main {
static int itemCount = 0;
static int bufferSize = 5;
public static void main(String[] args) {
Main m = new Main();
Thread objP = new Thread(new Producer(m, "Producer1"));
Thread objC = new Thread(new Consumer(m, "Consumer1"));
Thread objC2 = new Thread(new Consumer(m, "Consumer2"));
Thread objC3 = new Thread(new Consumer(m, "Consumer3"));
objP.start();
objC.start();
objC2.start();
objC3.start();
}
}
You are using notifyAll in the producer, which wakes up all consumer threads waiting on the monitor. If you want only one consumer to wake up, you should use notify From the API documentation:
notify()
Wakes up a single thread that is waiting on this object's monitor.
notifyAll()
Wakes up all threads that are waiting on this object's monitor.
It would also be better for your consumers to actually check that they can consume a resource when they are woken up. If you want to continue to use notifyAll, a consumer should be able to be awoken, and if insufficient resource is available, go back to waiting.
I suggest printing the main.itemCount. This will make it more obvious what the problems you have are.
You have to pay attention to when you are calling notify.
Why does your producer only call notify when there is exactly one item available? Shouldn't the producer call notify whenever there is an item available?
The consumer only tells the producer to wake up when there are 4 items (isn't this full?).
Actually changing notifyAll() to notify() kindoff worked!!! thanks for ua suggestion guys. Here is my code:
Producer class:
package com.source;
import java.util.Random;
public class Producer implements Runnable {
Object SharedObject = null;
String producerName = null;
Random rn = new Random();
public Producer(Main m, String s) {
this.SharedObject = m;
this.producerName = s;
}
public Producer(Main m) {
this.SharedObject = m;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == Main.bufferSize) {
try {
System.out
.println(this.producerName + "is sleeping and waiting for notification form Consumer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount++;
System.out.println(this.producerName + " Produced the item and the item count is : " + Main.itemCount);
if (Main.itemCount == 1) {
SharedObject.notify();
System.out.println("Producer Notified the cosumer to wake up");
}
}
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer Class:
package com.source;
import java.util.Random;
public class Consumer implements Runnable {
Object SharedObject = null;
String consumerName = null;
Random rn = new Random();
public Consumer(Main m, String s) {
SharedObject = m;
this.consumerName = s;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == 0) {
try {
System.out.println(this.consumerName + " is sleeping and waiting for notify from Producer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount--;
System.out.println(this.consumerName + " consumed 1 item and the item Count is " + Main.itemCount);
if (Main.itemCount == 4) {
SharedObject.notify();
System.out.println("Consumer notified the producer to wake up");
}
}
try {
int i = rn.nextInt(1000);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class:
package com.source;
public class Main {
static int itemCount = 0;
static int bufferSize = 5;
public static void main(String[] args) {
Main m = new Main();
Thread objP = new Thread(new Producer(m, "Producer1"));
Thread objC = new Thread(new Consumer(m, "Consumer1"));
Thread objC2 = new Thread(new Consumer(m, "Consumer2"));
Thread objC3 = new Thread(new Consumer(m, "Consumer3"));
Thread objP2 = new Thread(new Producer(m, "Producer2"));
Thread objP3 = new Thread(new Producer(m, "Producer3"));
objP.start();
objC.start();
objC2.start();
objC3.start();
objP2.start();
objP3.start();
}
}
Once again thanks to everyone for your valuable time and suggestions.
Sounds like you are past your initial problem but here's some more feedback.
I believe your real problem was not because of notifyAll() but because your buffer tests were if tests instead of while loops. There are classic race conditions where a thread gets awaken but there are no elements in the buffer. See my notes here. So you code should be something like:
while (Main.itemCount == Main.bufferSize) {
and
while (Main.itemCount == 0) {
Calling notifyAll() exacerbated the problem but the race conditions still exist even with just notify(). As you add more consumers or another producer you will see more problems.
Here is some other feedback.
Be very careful of locks within locks. That is a bad pattern typically and one that I use very infrequently. Do you really need consume() to be synchronized?
Object instance names should start with a lowercase letter so it should be sharedObject.
Any object that you are locking on should be private final if at all possible. You wouldn't want it changing to another object.
Using Main. anything is a bad pattern. How about creating an object with the itemCount and bufferSize and then passing the same instance of that object to all of our producer and consumers? It would also be the object you would lock on.
Be careful of sprinkling your thread code with System.out.println(...) messages as others have recommended. System.out is a synchronized class so this will add locks and memory synchronization that may move or fix the problem. Yes. Debugging threaded programs is hard.
Problem description : -
Step 1: Take input FILE_NAME from user at main thread.
Step 2: Perform 10 operations on that file (i.e count chars, count lines etc.. ), and all those 10 operations must be in septate threads. It means there must be 10 child threads.
Step 3: Main thread waits until all those child threads completed.
Step 4: Print result.
What I did :-
I did a sample code with 3 threads. I don't want file operation code from your side.
public class ThreadTest {
// This is object to synchronize on.
private static final Object waitObject = ThreadTest.class;
// Your boolean.
private static boolean boolValue = false;
public final Result result = new Result();
public static void main(String[] args) {
final ThreadTest mytest = new ThreadTest();
System.out.println("main started");
new Thread(new Runnable() {
public void run() {
System.out.println("Inside thread");
//Int initialiser
new Thread(new Runnable() {
public void run() {
System.out.println("Setting integer value");
mytest.result.setIntValue(346635);
System.out.println("Integer value seted");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
//String initialiser
new Thread(new Runnable() {
public void run() {
System.out.println("Setting string value");
mytest.result.setStringValue("Hello hi");
System.out.println("String value seted");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
//Boolean initialiser
new Thread(new Runnable() {
public void run() {
System.out.println("Setting boolean value");
mytest.result.setBoolValue(true);
System.out.println("Boolean value seted");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
System.out.println("Thread is finished");
//Notify to main thread
synchronized (ThreadTest.waitObject) {
ThreadTest.boolValue = true;
ThreadTest.waitObject.notifyAll();
}
}
}).start();
try {
synchronized (ThreadTest.waitObject) {
while (!ThreadTest.boolValue) {
ThreadTest.waitObject.wait();
}
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("main finished");
System.out.println("Result is : " + mytest.result.toString());
}
}
Problem :-
My above code is not giving correct answer. How can I do that?
Alternate solutions:
CountDownLatch class does the same. But I don't want to use that class.
I looked this similar solution and I want to use methods of Thread only.
You can do:
Thread t = new Thread() {
public void run() {
System.out.println("text");
// other complex code
}
};
t.start();
t.join();
This way you will wait until the thread finishes and just then continue. You can join multiple threads:
for (Thread thread : threads) {
thread.join();
}
I would recommend looking at the Executors framework first, and then look into the CompletionService.
Then you can write something like this:
ExecutorService executor = Executors.newFixedThreadPool(maxThreadsToUse);
CompletionService completion = new ExecutorCompletionService(executor);
for (each sub task) {
completion.submit(new SomeTaskYouCreate())
}
// wait for all tasks to complete.
for (int i = 0; i < numberOfSubTasks; ++i) {
completion.take(); // will block until the next sub task has completed.
}
executor.shutdown();
In Java 8 a far better approach is to use parallelStream()
Note: it is far easier to see exactly what these background tasks are doing.
public static void main(String[] args) {
Stream.<Runnable>of(
() -> mytest.result.setIntValue(346635),
() -> mytest.result.setStringValue("Hello hi"),
() -> mytest.result.setBoolValue(true) )
.parallel()
.forEach(Runnable::run);
System.out.println("main finished");
System.out.println("Result is : " + mytest.result.toString());
}
I took out the debug information and the sleep as these don't alter the outcome.
You may want to choose CountDownLatch from java.util.concurrent. From JavaDocs:
A synchronization aid that allows one or more threads to wait until a
set of operations being performed in other threads completes.
Sample code:
import java.util.concurrent.CountDownLatch;
public class Test {
private final ChildThread[] children;
private final CountDownLatch latch;
public Test() {
this.children = new ChildThread[4];
this.latch = new CountDownLatch(children.length);
children[0] = new ChildThread(latch, "Task 1");
children[1] = new ChildThread(latch, "Task 2");
children[2] = new ChildThread(latch, "Task 3");
children[3] = new ChildThread(latch, "Task 4");
}
public void run() {
startChildThreads();
waitForChildThreadsToComplete();
}
private void startChildThreads() {
Thread[] threads = new Thread[children.length];
for (int i = 0; i < threads.length; i++) {
ChildThread child = children[i];
threads[i] = new Thread(child);
threads[i].start();
}
}
private void waitForChildThreadsToComplete() {
try {
latch.await();
System.out.println("All child threads have completed.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class ChildThread implements Runnable {
private final String name;
private final CountDownLatch latch;
protected ChildThread(CountDownLatch latch, String name) {
this.latch = latch;
this.name = name;
}
#Override
public void run() {
try {
// Implementation
System.out.println(name + " has completed.");
} finally {
latch.countDown();
}
}
}
public static void main(String[] args) {
Test test = new Test();
test.run();
}
}
Output:
Task 1 has completed.
Task 4 has completed.
Task 3 has completed.
Task 2 has completed.
All child threads have completed.
There are many ways to approach this. Consider CountDownLatch:
import java.util.concurrent.CountDownLatch;
public class WorkerTest {
final int NUM_JOBS = 3;
final CountDownLatch countDownLatch = new CountDownLatch(NUM_JOBS);
final Object mutex = new Object();
int workData = 0;
public static void main(String[] args) throws Exception {
WorkerTest workerTest = new WorkerTest();
workerTest.go();
workerTest.awaitAndReportData();
}
private void go() {
for (int i = 0; i < NUM_JOBS; i++) {
final int fI = i;
Thread t = new Thread() {
public void run() {
synchronized(mutex) {
workData++;
}
try {
Thread.sleep(fI * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
};
t.start();
}
}
private void awaitAndReportData() throws InterruptedException {
countDownLatch.await();
synchronized(mutex) {
System.out.println("All workers done. workData=" + workData);
}
}
}
Check if all child threads are dead, every n seconds. Simple, yet effective method:
boolean allDead=false;
while(! allDead){
allDead=true;
for (int t = 0; t < threadCount; t++)
if(threads[t].isAlive()) allDead=false;
Thread.sleep(2000);
}