Lab 4 assignment is based on using the following solution for lab3’s part (b ) or your own solution, please attempt to implement Part C below:import java.io.*;import java.security.*;  public clas

Lab 4: Returning Information from a Thread ( Lab 3’s Part C and more!)


Lab 4 assignment is based on using the following solution for lab3’s part (b ) or your own solution, please attempt to implement Part C below:

import java.io.*;

import java.security.*;



public class DigestRunnable implements Runnable {


private File input;


public DigestRunnable(File input) {

this.input = input;

}


public void run() {

try {

FileInputStream in = new FileInputStream(input);

MessageDigest sha = MessageDigest.getInstance("SHA");

DigestInputStream din = new DigestInputStream(in, sha);

int b;

while ((b = din.read()) != -1) ;

din.close();

byte[] digest = sha.digest();

StringBuffer result = new StringBuffer(input.toString());

result.append(": ");

for (int i = 0; i < digest.length; i++) {

result.append(digest[i] + " ");

}

System.out.println(result);

}

catch (IOException e) {

System.err.println(e);

}

catch (NoSuchAlgorithmException e) {

System.err.println(e);

}

}

public static void main(String[] args) {

for (int i = 0; i < args.length; i++) {

File f = new File(args[i]);

DigestRunnable dr = new DigestRunnable(f);

Thread t = new Thread(dr);

t.start();

}

}

}


C) Returning Information from a Thread: One of the hardest things for programmers accustomed to traditional, single-threaded procedural models to grasp when moving to a multithreaded environment is how to return information from a thread. The run() method and the start() method don’t return any values.

Suppose that instead of simply printing out the SHA digest as in part (b), the digest thread needs to return the digest to the main thread of execution. Most people’s first reaction is to store the result in a field, then provide a getter method. Attempt to solve this problem with different solutions and discuss the issues.

To get you started, here is a first attempt to solve the problem: Describe what is the source of the error? Why it does not work? Could you modify this solution to work properly?

A Thread that uses an Accessor Method to return the result:

import java.io.*;

import java.security.*;



public class ReturnDigest extends Thread {


private File input;

private byte[] digest;


public ReturnDigest(File input) {

this.input = input;

}


public void run() {

try {

FileInputStream in = new FileInputStream(input);

MessageDigest sha = MessageDigest.getInstance("SHA");

DigestInputStream din = new DigestInputStream(in, sha);

int b;

while ((b = din.read()) != -1) ;

din.close();

digest = sha.digest();

}

catch (IOException e) {

System.err.println(e);

}

catch (NoSuchAlgorithmException e) {

System.err.println(e);

}

}

public byte[] getDigest() {

return digest;

}


}


A Main program that uses the Accessor Method to Get the Output of the Thread:


import java.io.*;



public class ReturnDigestUserInterface {

public static void main(String[] args) {

for (int i = 0; i < args.length; i++) {

// Calculate the digest

File f = new File(args[i]);

ReturnDigest dr = new ReturnDigest(f);

dr.start();

// Now print the result

StringBuffer result = new StringBuffer(f.toString());

result.append(": ");

byte[] digest = dr.getDigest();

for (int j = 0; j < digest.length; j++) {

result.append(digest[j] + " ");

}

System.out.println(result);

}

}


}


Hint for another more efficient solution: Let the thread tell the Main program when it is done by invoking a method in the main class that started it. This is called a callback because the thread calls back its creator when it’s finished. This solution is found in your lecture notes.


Lab4New (listener/ callback solution) This solution is also described in class lecture notes. The main program implements a digestlistener interface. This interface has a method for printing out calculated digests. The idea is that you create a fixed number of threads ( a thread pool) in the main program that each will work on a runnable object that calculates a file’s digest. An instance of the main program will subscribe to each thread (runnable object) that calculates a file’s digest. As soon as the digest is calculated, the digest listener ‘s method (for returning and printing digest) of the corresponding instance of the main program is invoked.


The new requirement in this lab is that you use ExecutorService interface for the thread pool in the main program.

( http://java.sun.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html )

The ExecutorService Interface

The ExecutorService interface supplements execute with a similar, but more versatile submit method. Like execute, submit accepts Runnable objects, but also accepts Callable objects, which allow the task to return a value. The submit method returns a Future object, which is used to retrieve the Callable return value and to manage the status of both Callable and Runnable tasks.

ExecutorService also provides methods for submitting large collections of Callable objects. Finally, ExecutorService provides a number of methods for managing the shutdown of the executor. To support immediate shutdown, tasks should handle interrupts correctly.

( http://java.sun.com/docs/books/tutorial/essential/concurrency/exinter.html )


Usage Example

Here is a sketch of a network service in which threads in a thread pool service incoming requests. It uses the preconfigured Executors.newFixedThreadPool(int) factory method:

class NetworkService {

private final ServerSocket serverSocket;

private final ExecutorService pool;

public NetworkService(int port, int poolSize) throws IOException {

serverSocket = new ServerSocket(port);

pool = Executors.newFixedThreadPool(poolSize);

}

public void serve() {

try {

for (;;) {

pool.execute(new Handler(serverSocket.accept()));

}

} catch (IOException ex) {

pool.shutdown();

}

}

}

class Handler implements Runnable {

private final Socket socket;

Handler(Socket socket) { this.socket = socket; }

public void run() {

// read and service request

}

}