Use threading to process file chunk by chunk - java

I have a arraylist which consists of 5000 IP Addresses. For each IP Address, I want to execute a SNMPGet request and a FTPDownload command. I want to implement it in a fashion, wherein at a time 2 different threads run simultaneously for the first five IP Addresses. After the execution of these IP Addresses, next 2 IP Addresses will be executed on these threads. Can anyone help how to do it?
Here, connection is a class which extends the thread and the work to be implemented is written in its run() method. Please help.
Connection newConnection =new Connection(0);
Connection newConnection1 =new Connection(1);
for(int i = 0; i < NE_list.getRowCount(); i=i+2)
{
if(NE_list.getValueAt(i, 0).toString().equals("true")) //Some condition here for the IP Address
{
newConnection.i=i;
newConnection1.i=i+1;
newConnection.runprogram();
newConnection1.runprogram();
}
}
class Connection extends Thread{
int i;
Connection(int val){
i=val;
}
void runprogram(){
start();
}
public void run(){
//SNMP and FTP Code here for IP Address in index i of NE_list
}
}

Executor Framework will be best suit for your solution. I have created one example here. You can increase the number of threads as per your requirement.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class SomeRunnable implements Runnable {
int threadNo = -1 ;
List<String> list = new ArrayList<String>();
public SomeRunnable(List list, int threadNo ) {
this.list.addAll(list);
this.threadNo =threadNo;
}
#Override
public void run() {
for (String element : list) {
System.out.println("By Thread:" + threadNo+", Processed Element:" +element);
}
}
}
public class ExecutorDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
list.add("Elem:"+i);
}
// Divide list
int divideIndex = list.size()/2;
//Create objects of Runnable
SomeRunnable obj1 = new SomeRunnable(list.subList(0, divideIndex),1);
SomeRunnable obj2 = new SomeRunnable(list.subList(divideIndex,list.size()),2);
//Create fixed Thread pool, here pool of 2 thread will created
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.execute(obj1);
pool.execute(obj2);
pool.shutdown();
}
}

Herewith adding working example having 5 threads. Just put the test.txt in your CLASS_PATH of the application.
class MyRunnable implements Runnable {
List<List<String>> records;
MyRunnable(List<List<String>> records){
this.records = records;
}
public void run(){
for(List list : records){
System.out.println(Thread.currentThread().getName() + " : "+list.toString());
}
}}
Main Class -
public class FileProcessThreads {
public List<List<String>> process(String fileName) throws IOException {
List<List<String>> records = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = null;
while((line = br.readLine()) != null){
List<String> listValues = Arrays.asList(line.split(" "));
records.add(listValues);
}
System.out.println(records.size());
return records;
}
public static void main(String[] args) throws IOException {
FileProcessThreads fp = new FileProcessThreads();
List<List<String>> records = fp.process("test.txt");
ExecutorService es = Executors.newFixedThreadPool(5);
int recordsInEachThread = (int) (records.size()/5);
System.out.println(recordsInEachThread);
MyRunnable my1 = new MyRunnable(records.subList(0, recordsInEachThread));
MyRunnable my2 = new MyRunnable(records.subList(recordsInEachThread+1, recordsInEachThread*2));
MyRunnable my3 = new MyRunnable(records.subList(recordsInEachThread*2 + 1, recordsInEachThread*3));
MyRunnable my4 = new MyRunnable(records.subList(recordsInEachThread*3 + 1, recordsInEachThread*4));
MyRunnable my5 = new MyRunnable(records.subList(recordsInEachThread*4 + 1, records.size() - 1));
es.execute(my1);
es.execute(my2);
es.execute(my3);
es.execute(my4);
es.execute(my5);
es.shutdown();
}}

Related

sorting files using multithreading in java

I was given an assignment to write all ordered contents of given files into a result.txt. At first, the filenames are split into different Arraylists where each file contains a label in a format #n/N where N is the total number of files. e.g.
British explorer James Clark Ross led the first
expedition to reach the north magnetic pole
#001/004
from a file 1831-06-01.txt
The problem with my code is that it has written in order 1,4,2,3 respectively. However, the result must be in order 1,2,3,4. This may be due to a lack of synchronization. Nonetheless, I am still struggling to fix the problem.
This is my code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
class PopThread implements Runnable {
ArrayList<String> fileList;
public PopThread(ArrayList<String> fileList) {
this.fileList = fileList;
}
#Override
public void run() {
//System.out.println("running\n");
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
long startTime = System.nanoTime();
System.out.println("fileList: " + fileList);
ArrayList<String> sortedFileList = sortFiles(fileList);
File resultFile = new File("result.txt");
for (String filename : sortedFileList) {
Writer w1 = new Writer(filename, resultFile);
Thread t = new Thread(w1);
t.setPriority(Thread.MAX_PRIORITY);
t.start();
}
long stopTime = System.nanoTime();
//System.out.println("Total execution time: " + (stopTime - startTime));
}
public ArrayList<String> readFiles(String filename) {
ArrayList<String> list = new ArrayList<String>();
try {
File myObj = new File(filename);
Scanner s = new Scanner(myObj);
while (s.hasNext()) {
list.add(s.next());
}
s.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return list;
}
public int getNumber(String filename) {
String lastLine = "";
String sCurrentLine;
int identifier_integer = -1;
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
while ((sCurrentLine = br.readLine()) != null) {
lastLine = sCurrentLine;
}
String identifier_number = lastLine.substring(1,4);
identifier_integer = Integer.parseInt(identifier_number);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return identifier_integer;
}
public ArrayList<String> sortFiles(ArrayList<String> listFileName) {
int i = listFileName.size();
boolean sorted = false;
while ( (i > 1) && (!(sorted)) ) {
sorted = true;
for (int j = 1; j < i; j++) {
if ( getNumber(listFileName.get(j-1)) > getNumber(listFileName.get(j)) ) {
String temp = listFileName.get(j-1);
listFileName.set(j-1, listFileName.get(j));
listFileName.set(j, temp);
sorted = false;
}
}
i--;
}
return listFileName;
}
}
class Writer implements Runnable {
String filename;
File resultFile;
public Writer(String filename, File resultFile) {
this.filename = filename;
this.resultFile = resultFile;
}
#Override
public void run() {
String content;
content = readFromFile(filename);
writeToFile(resultFile, content);
}
private static void writeToFile(File resultFile, String content) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile, true));
writer.write(content);
//writer.write("file content written");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
static String readFromFile(String filename) {
StringBuffer content = new StringBuffer();
try {
String text;
BufferedReader reader = new BufferedReader(new FileReader(filename));
while ((text = reader.readLine()) != null) {
content.append(text);
content.append("\n");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return content.toString();
}
}
public class q4 {
public static void main(String[] args) {
ArrayList<String> filesOne = new ArrayList<String>();
filesOne.add("1831-06-01.txt");
filesOne.add("2003-08-27.txt");
ArrayList<String> filesTwo = new ArrayList<String>();
filesTwo.add("1961-04-12.txt");
filesTwo.add("1972-12-11.txt");
PopThread popRunnableOne = new PopThread(filesOne);
PopThread popRunnableTwo = new PopThread(filesTwo);
Thread threadOne = new Thread(popRunnableOne);
Thread threadTwo = new Thread(popRunnableTwo);
threadOne.start();
threadTwo.start();
try {
threadOne.join();
threadTwo.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
( NOTE: The class q4 cannot be altered)
This assignment is horrible. You have my sympathy.
Your two threads will have to communicate with each other. Each thread will have to know, what is the filename that the other thread wants to output next. And, they will have to take turns. Each thread needs to loop:
While the date on my next file is less than or equal to the date on the other thread's next file, output my next file,
Tell the other thread, "it's your turn,"
If I have no more files, then exit (return from the run() method), otherwise, wait for the other thread to tell me it's my turn again,
Go back to step 1.
Having to take turns is the worst part of the assignment. Any time you find yourself needing to make threads take turns doing something—any time you need to make threads do things in a particular order—that's a clear sign that all of the things should be done by a single thread.
The only way threads can communicate is through shared variables. Your instructor has done you a huge disservice by telling you not to modify the q4 class. That prevents you from passing any shared objects in to your PopThread implementation through its constructor.
The only other way your two threads can share any variables is by making the variables static. Forcing you to use static is the second worst part of the assignment. If you go on to study software engineering, you will learn that static is an anti-pattern. Programs that use static variables are brittle (i.e., hard to modify), and they are hard to test.
Forcing you to use static variables also will make your threads do extra work to figure out who is who. Normally, I would do something like this so that each thread would automatically know which state is its own, and which belongs to the other guy:
class SharedState { ... }
class PopThread {
public PopThread(
SharedState myState,
SharedState otherThreadState,
ArrayList<String> fileList
) {
this.myState = myState;
this.otherGuyState = otherThreadState;
this.fileList = fileList;
...initialize this.myState...
}
...
}
class q4 {
public static void main(String[] args) {
SharedState stateOne = new SharedState();
SharedState stateTwo = new SharedState();
PopThread popRunnableOne = new PopThread(stateOne, stateTwo, filesOne);
PopThread popRunnableTwo = new PopThread(stateTwo, stateOne, filesTwo);
...
}
}
The best way I can think of with static variables would be to have an array of two SharedState, and have the threads use an AtomicInteger to each assign themself one of the two array slots:
class PopThread {
static SharedState[] state = new SharedState [2];
static AtomicInteger nextStateIndex = new AtomicInteger(0);
public PopThread(
SharedState myState,
SharedState otherThreadState,
ArrayList<String> fileList
) {
myStateIndex = nextStateIndex.getAndIncrement();
otherGuysStateIndex = myStateIndex ^ 1;
this.fileList = fileList;
...initialize state[myStateIndex]...
}
...
}

Java create thread with parameters

I have a program that counts several times a word in the text.
I want the loop to be in a separate thread. How can I pass parameters articles and stringToSearch to the thread, or set the global parameters?
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int numberArticles = s.nextInt();
ArrayList<Article> articles = new ArrayList<>();
for(int i = 0; i < numberArticles; i++) {
String articleName = s.nextLine();
String content = "";
File file = new File(articleName + ".txt");
BufferedReader br;
try {
br = new BufferedReader(new FileReader(file));
String st;
while ((st = br.readLine()) != null) {
content += st;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
articles.add(new Article(articleName, content));
}
String stringToSearch = s.nextLine();
MyThread myThread = new MyThread();
myThread.start();
}
}
public class MyThread extends Thread {
public void run(){
for(Article article : articles) {
int counter = 0;
String[] words = article.getContent().split(" ");
for (String word : words) {
if(word.equals(stringToSearch)) {
counter++;
}
}
}
}
}
You are extending Thread with your custom class. And you can add any number of any additional properties to that class (MyThread). And you can create a constructor in MyThread to pass all those parameters.
Here's an example showing how to pass some values into the constructor for your MyThread class. This passes two things into the constructor which then saves them to private members which can then be used within the run() method. I removed most of the other code from your question since it wasn't required for this explanation.
import java.util.ArrayList;
public class Scratch2 {
public static void main(String[] args) {
ArrayList<Article> articles = new ArrayList<>();
String stringToSearch = "...";
MyThread myThread = new MyThread(articles, stringToSearch);
myThread.start();
}
}
public class MyThread extends Thread {
private final ArrayList<Article> articles;
private final String stringToSearch;
public MyThread(ArrayList<Article> articles, String stringToSearch) {
this.articles = articles;
this.stringToSearch = stringToSearch;
}
public void run() {
for (Article article : articles) {
// ... do things with "stringToSearch"
}
}
}
class Article {
// more stuff here
}

Java concurrent file writing - should fail

I've been testing to write multiple items to a filesystem, fully expecting to get a failure where by one thread overwrites anthers data, or interleaves with the data from another item.
However the following code unexpectedly passes.
Why is the data from one thread not overwriting the data from another thread? All the threads share one writer. Does the code pass because of a JVM implementation detail, or can it genuinely be expected to not mix up individual items.
I've seen some other quests about multiple threads writing to the same file but these were about performance optimizations. Note the import style is just for brevity when posting.
package com.test;
import static org.junit.Assert.assertEquals;
import java.io.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;
import org.springframework.boot.CommandLineRunner;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DiskWriterApplication implements CommandLineRunner {
public static void main(String[] args) throws Exception {
new DiskWriterApplication().run(args);
}
#Override
public void run(String... args) throws Exception {
Path path = Paths.get(System.getProperty("user.home")+"/java-file.txt");
if (!Files.exists(path)) {
Files.createFile(path);
} else {
Files.delete(path);
Files.createFile(path);
}
BufferedWriter writer = Files.newBufferedWriter(path, Charset.forName("UTF-8"), StandardOpenOption.APPEND);
Thread[] threads = new Thread[4];
for (int i=0; i< 4; i++) {
threads[i] = new Thread(new DataWriter(writer, createDataItems(i)));
}
Arrays.asList(threads).forEach(Thread::start);
Arrays.asList(threads).forEach(t-> {
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
writer.close();
//Verify Lines were written correctly
ObjectMapper mapper = new ObjectMapper();
MappingIterator<Data> valueIterator = mapper.readerFor(Data.class).readValues(Files.newInputStream(path));
Set<String> uniqueItems = new HashSet<>();
int[] groupItemCount = new int[4];
while (valueIterator.hasNext())
{
Data item = valueIterator.next();
assertEquals("First Item and second Item should be equal", item.firstValue, item.secondValue);
assertEquals(10, item.innerObject.size());
assertEquals(20, item.listValues.size());
for (int i = 0 ; i< 10; i++) {
assertEquals(item.firstValue, item.innerObject.get("innerProp"+i));
}
for (int i = 0 ; i< 20; i++) {
assertEquals(item.firstValue, item.listValues.get(i));
}
uniqueItems.add(item.firstValue);
groupItemCount[item.group]++;
}
System.out.println("Got " + uniqueItems.size() + " uniqueItems");
assertEquals("Should be 4000 uniqueItems", 4000, uniqueItems.size());
assertEquals("Should be 1000 items in group[0]", 1000, groupItemCount[0]);
assertEquals("Should be 1000 items in group[1]", 1000, groupItemCount[1]);
assertEquals("Should be 1000 items in group[2]", 1000, groupItemCount[2]);
assertEquals("Should be 1000 items in group[3]", 1000, groupItemCount[3]);
}
private List<Data> createDataItems(int groupNumber) {
List<Data> items = new ArrayList<>();
for (int i =0; i<1000; i++) {
Data item = new Data();
item.group = groupNumber;
item.itemNumber = i;
item.firstValue = "{group" + groupNumber + "item" + i + "}";
item.secondValue = "{group" + groupNumber + "item" + i + "}";
for (int j =0; j< 10; j ++) {
item.addInnerProperty("innerProp"+j , "{group" + groupNumber + "item" + i + "}");
}
for (int j=0; j<20; j++) {
item.addListValue("{group" + groupNumber + "item" + i + "}");
}
items.add(item);
}
return items;
}
private class DataWriter implements Runnable {
private ArrayList<String> data;
private PrintWriter writer;
public DataWriter(BufferedWriter writer, List<Data> items) {
this.writer = new PrintWriter(writer);
this.data = new ArrayList<String>();
ObjectMapper mapper = new ObjectMapper();
for (Data i : items) {
try {
String stringValue = mapper.writeValueAsString(i);
data.add(stringValue);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public void run() {
System.out.println("Starting batch");
data.forEach(t -> {
writer.println(t);
writer.flush();
});
System.out.println("finishing batch");
}
}
public static class Data {
public int itemNumber;
public int group;
#JsonProperty
private String firstValue;
#JsonProperty
private String secondValue;
#JsonProperty
private Map<String, String> innerObject = new HashMap<>();
#JsonProperty
private List<String> listValues = new ArrayList<>();
public void addInnerProperty(String key, String value){
this.innerObject.put(key, value);
}
public void addListValue(String value) {
this.listValues.add(value);
}
}
}
As you can see in the others threads asking the same thing :
Writing a file using multiple threads in java
Is writting on file using bufferwriter initialized by filewriter thread safe or not?
the BufferedWriter is synchronized and thread-safe

Wait in ForkJoin Pool ( Java )

I am using Fork join pool in java for multitasking. Now i came across a situation where, for every task, I need to hit a url then wait for 10 minutes and then again hit another url to read the data. Now the problem is that for those 10 minutes my CPU is idle and not starting another tasks ( more than those defined in fork join pool).
static ForkJoinPool pool = new ForkJoinPool(10);
public static void main(String[] args){
List<String> list = new ArrayList<>();
for(int i=1; i<=100; i++){
list.add("Str"+i);
}
final Tasker task = new Tasker(list);
pool.invoke(task);
public class Tasker extends RecursiveAction{
private static final long serialVersionUID = 1L;
List<String> myList;
public Tasker(List<String> checkersList) {
super();
this.myList = checkersList;
}
#Override
protected void compute() {
if(myList.size()==1){
System.out.println(myList.get(0) + "start");
//Date start = new Date();
try {
Thread.sleep(10*60*1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(myList.get(0) + "Finished");
}
else{
List<String> temp = new ArrayList<>();
temp.add( myList.get( myList.size()-1 ) );
myList.remove( myList.size()-1 );
Tasker left = new Tasker(myList);
Tasker right = new Tasker(temp);
left.fork();
right.compute();
left.join();
}
}
Now What should I do so that CPU picks all the tasks and then wait parallaly for them.
Unfortunately, ForkJoinPool does not work well in the face of Thread.sleep(), because it designed for many short tasks that finish quickly, rather than tasks that block for a long time.
Instead, for what you are trying to accomplish, I would recommend using ScheduledThreadPoolExecutor and dividing your task into two parts.
import java.util.*;
import java.util.concurrent.*;
public class Main {
static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(10);
public static void main(String[] args){
for(int i=1; i<=100; i++){
pool.schedule(new FirstHalf("Str"+i), 0, TimeUnit.NANOSECONDS);
}
}
static class FirstHalf implements Runnable {
String name;
public FirstHalf(String name) {
this.name = name;
}
public void run() {
System.out.println(name + "start");
pool.schedule(new SecondHalf(name), 10, TimeUnit.MINUTES);
}
}
static class SecondHalf implements Runnable {
String name;
public SecondHalf(String name) {
this.name = name;
}
public void run() {
System.out.println(name + "Finished");
}
}
}
If Java provides a thread pool which allows releasing the underlying resources (that is, the kernel thread participating in the thread pool) during a Thread.sleep(), you should use that instead, but I currently do not know of one.
According to docs forkJoin basic use section tells:
if (my portion of the work is small enough)
do the work directly
else
split my work into two pieces
invoke the two pieces and wait for the results
Hopefully this meets your need if you are using forkjoin
public class Tasker extends RecursiveAction {
static ForkJoinPool pool = new ForkJoinPool(10);
static int threshold = 10;
public static void main(String[] args){
List<String> list = new ArrayList<>();
for(int i=1; i<=100; i++){
list.add("Str"+i);
}
final Tasker task = new Tasker(list);
pool.invoke(task);
}
private static final long serialVersionUID = 1L;
List<String> myList;
public Tasker(List<String> checkersList) {
super();
this.myList = checkersList;
}
void computeDirectly() {
for(String url : myList){
System.out.println(url + " start");
}
//Date start = new Date();
try {
//keep hitting url
while (true) {
for(String url : myList) {
//url hitting code here
System.out.println(url + " hitting");
}
Thread.sleep(10 * 60 * 1000);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(String url : myList){
System.out.println(url + " Finished");
}
}
#Override
protected void compute() {
if (myList.size() <= threshold) {
computeDirectly();
return;
}
//temp list have only one url
//List<String> temp = new ArrayList<>();
//temp.add( myList.get( myList.size()-1 ) );
//myList.remove( myList.size()-1 );
//Tasker left = new Tasker(myList);
//Tasker right = new Tasker(temp);
//left.fork();
//right.compute();
//left.join();
List<String> first = new ArrayList<>();
List<String> second = new ArrayList<>();
//divide list
int len = myList.size();
int smHalf = len / 2;//smaller half
first = myList.subList(0, smHalf);
second = myList.subList(smHalf + 1, len);
invokeAll(new Tasker(first), new Tasker(second));
}
}

Passing objects from a pool to a runnable class

I have an pool of objects in a blockingQueue. Now i want to assign objects from the queue to a thread and use it inside the run method.
What is the best way of doing it?
Here is a sample code i am using to build the pool:
public class ConsumerPool {
private static Logger log;
//building consumer Pool
#SuppressWarnings("finally")
public BlockingQueue<OAuthConsumer> buildConsumerPool() {
BlockingQueue<OAuthConsumer> consumerObjectsQueue = null;
try {
//setting the config path
PropertyHandler.setConfigPath(propertiesMain);
String twitterPath = PropertyHandler.getProperty("twitterPath");
//setting config for twitter
PropertyHandler.setConfigPath(twitterPath);
//Blocking Linked Queue
consumerObjectsQueue = new LinkedBlockingQueue<OAuthConsumer>();
//fetching required tokens for all apps
String consumerKeySet = PropertyHandler.getProperty("consumerKey");
String consumerSecretSet = PropertyHandler.getProperty("consumerSecret");
String accessTokenSet = PropertyHandler.getProperty("accessToken");
String tokenSecretSet = PropertyHandler.getProperty("tokenSecret");
String[] splitconsumerKeys = consumerKeySet.split(",");
String[] splitconsumerSecret = consumerSecretSet.split(".");
String[] splitaccessToken = accessTokenSet.split(",");
String[] splittokenSecret = tokenSecretSet.split(".");
//creating consumer objects for each app
for (int i= 0; i< splitconsumerKeys.length; i++) {
log.info("constructing consumer object for twitter api " +i);
String consumerKey = splitconsumerKeys[i];
String consumerSecret = splitconsumerSecret[i];
String accessToken = splitaccessToken[i];
String tokenSecret = splittokenSecret[i];
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
consumer.setTokenWithSecret(accessToken, tokenSecret);
consumerObjectsQueue.put(consumer);
log.info("added the consumer object to que pool");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return consumerObjectsQueue;
}
}
That is used to build the object pool.
Here is the way i want to create threads.
public class MrRunnable implements Runnable {
private String toFireUrl;
MrRunnable(String url){
}
#Override
public void run() {
// do some function here
}
}
public class Main {
public static void main(String[] args) {
// We will create 500 threads
for (int i = 0; i < 500; i++) {
Runnable task = new MrRunnable("some new url");
Thread worker = new Thread(task);
//start the thread
worker.start();
}
}
}
Now i want to access the objects in the pool via a thread. In the main program should i pass the object from the consumer pool to runnable class during the creation of MrRunnable Object or is there any other way i can do it ?
the constructor of MrRunnable should get a reference to the queue

Categories

Resources