Concurrent Runnable/Callable

In the Java concurrency library, an executor service schedules and executes tasks, choosing the threads on which to run them.
Runnable task = () -> { ... };
ExecutorService executor = ...;
executor.execute(task);
public static void mainRunnable(String[] args) {
		Runnable hellos = () -> {
		for (int i = 1; i <= 100; i++)
			System.out.println("Hello " + i);
		};
		Runnable goodbyes = () -> {
		for (int i = 1; i <= 100; i++)
			System.out.println("Goodbye " + i);
		};
		ExecutorService executor = Executors.newCachedThreadPool();
		executor.execute(hellos);
		executor.execute(goodbyes);
	}
A Runnable carries out a task, but it doesn't yield a value. If you have a task that computes a result, use the Callable interface instead. Its call method returns a value

ExecutorService executor = Executors.newFixedThreadPool();
Callable<V> task = ...;
Future<V> result = executor.submit(task);
As a bonus, the call method can throw arbitrary exceptions which can be relayed to the code that obtains the result.
When you submit the task, you get a future—an object that represents a computation whose result will be available at some future time. The Future interface has the following methods:
V get() throws InterruptedException, ExecutionException
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
boolean cancel(boolean mayInterruptIfRunning)
boolean isCancelled()
boolean isDone()

Example Searching files in dir with Futures

String word = ...;
Set<Path> paths = ...;
List<Callable<Long>> tasks = new ArrayList<>();
for (Path p : paths) tasks.add(
() -> { return number of occurrences of word in p });
List<Future<Long>> results = executor.invokeAll(tasks);
// This call blocks until all tasks have completed
long total = 0;
for (Future<Long> result : results) total += result.get();
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
 
public class FutureTest {
 
 
    public static void main(String[] args) { 
    	Scanner input = new Scanner(System.in);
    	System.out.print("Please enter directory (e.g. /usr/local/jdk7.0/src): ");
    	String dir = input.nextLine();
    	System.out.print("Please enter keyword (e.g. myFile): ");
    	String keyword = input.nextLine();
    	MatchCounter countFiles = new MatchCounter(new File(dir), keyword);
    	FutureTask<Integer> tsk = new FutureTask<Integer>(countFiles);
    	Thread thread = new Thread(tsk);
    	thread.start();
		
    	try {
    		System.out.println(tsk.get() + " matching files.");
    	} catch (ExecutionException e) {
    		e.printStackTrace();
    	} catch (InterruptedException e) {
    		}
    }
}
 
/**
 * This task counts the files in a directory and its subdirectories that contain
 * a given keyword.
 */
class MatchCounter implements Callable<Integer> {
 
    /**
     * 
     * dir the directory in which to start the search
     * keyword the keyword to look for
     * 
     */
     
    private File dir;
    private String keyword;
    private int counter;
     
    public MatchCounter(File directory, String keyword) {
    	this.dir = directory;
    	this.keyword = keyword;
    }
 
    public Integer call() {
    	counter = 0;
    	try {
    		File[] files = dir.listFiles();
    		ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();
    		for (File file : files) {
    			if (file.isDirectory()) {
    				MatchCounter counter = new MatchCounter(file, keyword);
    				FutureTask<Integer> task = new FutureTask<Integer>(counter);
    				results.add(task);
    				Thread t = new Thread(task);
    				t.start();
    			} else {
    				if (search(file)) {
    					counter++;
    				}
    			}
    		}
    		for (Future<Integer> result : results) {
    			try {
    				counter += result.get();
    			} catch (ExecutionException e) {
    				e.printStackTrace();
    			}
    		}
    	} catch (InterruptedException e) {
    		}
    	
    	return counter;
    }
 
    /**
     * Searches a file for a given keyword.
     *
     *  file the file to search
     *  returns true if the keyword is contained in the file
     */
    public boolean search(File file) {
    	try {
    		System.out.println(file.getCanonicalPath());
    		Scanner in = new Scanner(new FileInputStream(file));
    		boolean found = false;
    		while (!found && in.hasNextLine()) {
    			String line = in.nextLine();
    			if (line.contains(keyword)) {
    				found = true;
    			}
    		}
    		in.close();
    		return found;
    	} catch (IOException e) {
    		return false;
    	}
    }
}