Reputation: 663
I would like to execute 3 methods at same time in Java (obviously I need threads), and that I would like to execute not in separate class and not in my main method, but in my custom method. Can it be done?
I have find this piece of code - Execute Multiple Methods Simaltaneously Using Thread In Java and reused best marked answer for my example, with parameters that I have:
private void fetchData() {
boolean t1_run = true;
boolean t2_run = true;
boolean t3_run = true;
int SLEEP_TIME = 100;//Configurable.
Thread thread1 = new Thread() {
public void run() {
while (t1_run)
{
try
{
subjects = new BeanItemContainer<KltSubject>(KltSubject.class, clijentService.getSubjecteByType(Integer.valueOf(creditor)));
Thread.sleep(SLEEP_TIME);//So that other thread also get the chance to execute.
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
};
Thread thread2 = new Thread() {
public void run() {
while (t2_run)
{
try
{
programs = new BeanItemContainer<Program>(Program.class, creditService.getAllPrograms());
Thread.sleep(SLEEP_TIME);//So that other thread also get the chance to execute.
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
};
Thread thread3 = new Thread() {
public void run() {
while (t3_run)
{
try
{
credits = new BeanItemContainer<CreditExt>(CreditExt.class, creditService.getAllCredits());
Thread.sleep(SLEEP_TIME);//So that other thread also get the chance to execute.
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
};
thread1.start();
thread2.start();
thread3.start();
}
Now, before I've put my variables in threads (variables named: subjects, programs and credits), I could easily get their values (these variables you can see in above code in this example in their run methods, but are defined outside my fetchData() method and are visible).
After setting code like this, and executing it, I recieve null pointer exception because obviously varaibles are not seen any more after threads are executed. How to get that values after execution in threads?
P.S. can this code be written more elegantly, with less lines of code? If Java 8 (or Java 7) can done it - show me please how?
Upvotes: 0
Views: 1316
Reputation: 298469
You can simply use a CompletableFuture
:
CompletableFuture<BeanItemContainer<KltSubject>> job1 = CompletableFuture.supplyAsync(() ->
new BeanItemContainer<>(KltSubject.class, clijentService.getSubjecteByType(creditor)));
CompletableFuture<BeanItemContainer<Program>> job2 = CompletableFuture.supplyAsync(() ->
new BeanItemContainer<>(Program.class, creditService.getAllPrograms()));
CompletableFuture<BeanItemContainer<CreditExt>> job3 = CompletableFuture.supplyAsync(() ->
new BeanItemContainer<>(CreditExt.class, creditService.getAllCredits()));
subjects = job1.join();
programs = job2.join();
credits = job3.join();
The method supplyAsync
will initiate the asynchronous computation of a value and join
will return the computed value, waiting, if necessary. But if all three actions imply querying the same database, it might be possible, that you don’t gain any performance advantage as the database may be the limiting factor.
Upvotes: 0
Reputation: 38950
Use advanced Threading API : ExecutorService invokeAll()
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException
Executes the given tasks, returning a list of Futures holding their status and results when all complete.
Future.isDone()
is true for each element of the returned list. Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress.
Sample code:
ExecutorService service = Executors.newFixedThreadPool(3);
List<MyCallable> futureList = new ArrayList<MyCallable>();
MyCallable1 myCallable1 = new MyCallable1(); // your first thread
MyCallable2 myCallable2 = new MyCallable2(); // your second thread
MyCallable3 myCallable1 = new MyCallable3(); // your third thread
futureList.add(myCallable1);
futureList.add(myCallable2);
futureList.add(myCallable3);
System.out.println("Start");
try{
List<Future<Long>> futures = service.invokeAll(futureList);
for(Future<Long> future : futures){
try{
System.out.println("future.isDone = " + future.isDone());
System.out.println("future: call ="+future.get());
}
catch(Exception err1){
err1.printStackTrace();
}
}
}catch(Exception err){
err.printStackTrace();
}
service.shutdown();
You can have a look into few more examples in this article
Upvotes: 1
Reputation: 22474
You can use join()
to wait for the threads to finish.
eg:
thread1.join();
thread2.join();
thread3.join();
when all the threads are done, the variables shouldn't be null. Making this more compact depends on what exactly you're trying to do. Here is an example:
private List<Result> fetchData() {
final List<Result> results = new ArrayList<Result>();
List<Thread> threads = new ArrayList<Thread>();
for(int i = 0; i < 3; i++){
Thread t = new Thread() {
public void run() {
Result result = getResult();
synchronized(results) {
results.add(result);
}
}
};
t.start();
threads.add(t);
}
for(Thread t:threads) {
t.join();
}
return results;
}
Upvotes: 0