I have problem converting my code with the runnable interface to the callable interface in the following code. I need to change, because I need to return a Sting[][] isR
s by the threads.
When I just change the interface to callable
and chande .run()
to .call()
, then new Thread(new Worker(startSignal, doneSignal, i)).start();
wont work.
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(3); // 3 tasks
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final int threadNumber;
// you can pass additional arguments as well
Worker(CountDownLatch startSignal, CountDownLatch doneSignal, int threadNumber) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.threadNumber = threadNumber;
}
public void run() {
try {
startSignal.await();
if (threadNumber == 1) {
String[][] isRs = getIS(erg1, erg2, request);
}
if (threadNumber == 2) {
getIW(erg1, erg2, request);
}
if (threadNumber == 3) {
getIN(search_plz, request);
}
doneSignal.countDown();
} catch (InterruptedException ex) {
System.out.println(ex);
}
}
}
// 3 new threads are started
for (int i = 1; i <= 3; i++) {
new Thread(new Worker(startSignal, doneSignal, i)).start();
}
startSignal.countDown(); // let all threads proceed
try {
doneSignal.await(); // wait for all to finish
// all 3 tasks are finished and do whatever you want to do next
} catch (Exception e) {
}
You cannot pass a Callable
into a Thread
to execute.
Use the ExecutorService
to execute the Callable
object.
You can give it Callable
objects to run using its submit()
method:
<T> Future<T> submit(Callable<T> task)
Your class should look like:
class Worker {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final int threadNumber;
Worker(
CountDownLatch startSignal,
CountDownLatch doneSignal,
int threadNumber
){
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.threadNumber = threadNumber;
}
public String[][] getSomeStrArrArr() {
try {
startSignal.await();
if (threadNumber == 1) {
System.out.println("Running thread number 1");
}
if (threadNumber == 2) {
System.out.println("Running thread number 2");
}
if (threadNumber == 3) {
System.out.println("Running thread number 3");
}
doneSignal.countDown();
} catch (InterruptedException ex) {
System.out.println(
"Thread number "+threadNumber+" has been interrupted."
);
}
// replace these 2 lines with the actual code to get the String[][]
String[][] someStrArrArr = new String[1][1];
someStrArrArr[0][0] = "Done with thread number "+threadNumber;
return someStrArrArr;
}
public Callable<String[][]> getSomeCallableStrArrArr(){
return new Callable<String[][]>() {
public String[][] call() throws Exception {
return getSomeStrArrArr();
}
};
}
}
And you'd start it like:
ExecutorService pool = Executors.newFixedThreadPool(3);
Set<Future<String[][]>> set = new HashSet<Future<String[][]>>();
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(3);
for (int i=1;i<=3;i++) {
Worker worker = new Worker(startSignal,doneSignal,i);
Callable<String[][]> callable =
worker.getSomeCallableStrArrArr();
Future<String[][]> future = pool.submit(callable);
set.add(future);
}
And, to get and print the result strings:
for(Future<String[][]> future : set){
String[][] result = future.get();
for (String[] strArr: result){
for (String str: strArr){
System.out.println(str);
}
}
}
But this design can be improved. Have a look at the following documentation on Callable
to see how it differenciates from Runnable
and how you can get advantage from those differences and implent it properly:
Also check out this link where I've written an example based on your code you can run and fiddle with: http://ideone.com/blUQm0