I want to do a hash on every item from an arraylist and basically return it on the main. But for example a have this:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
public class hash extends Thread {
private Thread t = null;
private MessageDigest md = null;
private StringBuffer sb = null;
private String message = null;
private ArrayList<String> list = null;
private int count = 0;
public hash(ArrayList<String> list) {
this.list = list;
}
public final void mdstart() {
for(String item:list){
this.message=item;
if(t==null){
t = new Thread(this);
t.start();
}
count++;
}
System.out.println("end: "+this.count);
}
#Override
public final void run() {
System.out.println("run: "+this.count);
try {
md = MessageDigest.getInstance("MD5");
md.update(this.message.getBytes());
byte[] digest = md.digest();
sb = new StringBuffer();
for (byte hash : digest) {
sb.append(String.format("%02x", hash));
}
System.out.println(this.message + " : " + sb.toString());
} catch (NoSuchAlgorithmException ex) {
System.out.println("no such algorithm exception : md5");
System.exit(1);
}
}
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add("message" + i);
}
new hash(list).mdstart();
}
}
and the output is:
end: 10
run: 10
message9 : 99f72d2de922c1f14b0ba5e145f06544
which means that the program run only the last one thread from those I expect.
You are storing your Thread in t, which is null at the start but after creating the first Thread, it isn't null anymore, thus your if fails and no new Thread is created. Then you try to modify the message while this Thread runs... Honestely, the whole thing is a mess. Even if you were to create 10 Threads, they would all point to the same hash() object where the message variable is changing randomly without knowing if any Thread has already finished working.
For example, the following could happen:
You start the Thread for first message
Thread has not yet run, but your for loop already sets the message to the 2nd one
The thread runs and calculates the message for the 2nd message
Message 3 is set. Nothing happens since Thread is already finished.
Message 4 is set, again, nothing happens as the Thread is done
etc.
To fix it:
Remove the list variable from hash.
Create a new hash() object for each hashcode/message
Start a new thread for each hash() object. Then it should work.
The problem is that your code will start only one thread:
if(t==null){
t = new Thread(this);
t.start();
}
Once the first thread is started, t is no longer null, so no new threads would be created.
To fix this problem, make an array of threads, and set threads[count++] to the newly created thread in your loop. Once the loop is over, you can join your threads to make sure they all finish before mdstart() returns:
public final void mdstart() {
Thread[] threads = new Thread[list.size()];
for(String item:list){
this.message=item;
threads[count] = new Thread(this);
threads[count].start();
count++;
}
for (Thread t : threads) {
t.join();
}
System.out.println("end: "+this.count);
}
Note: This will fix the start-up portion of your code. You would need to deal with synchronization issues in your run() method to complete the fix.
Related
I'm writing a console application to read json files and then do some processing with them. I have 200k json files to process, so I'm creating a thread per file. But I would like to have only 30 active threads running. I don't know how to control it in Java.
This is the piece of code I have so far:
for (String jsonFile : result) {
final String jsonFilePath = jsonFile;
Thread thread = new Thread(new Runnable() {
String filePath = jsonFilePath;
#Override
public void run() {
// Do stuff here
}
});
thread.start();
}
result is an array with the path of 200k files. From this point, I'm not sure how to control it. I thought about a List<Thread> and then in each thread implements a notifier and when they finish just remove from the list. But then I would have to make the main thread sleep and then wake-up. Which feels weird.
How can I achieve this?
I would suggest to not create one thread per file. Threads are limited resources. Creating too many can lead to starvation or even program abortion.
From what information was provided, I would use a ThreadPoolExecutor. Constructing such an Executor with a limited amount of threads is quite simple thanks to Executors::newFixedSizeThreadPool:
ExecutorService service = Executors.newFixedSizeThreadPool(30);
Looking at the ExecutorService-interface, method <T> Future<T> submit​(Callable<T> task) might be fitting.
For this, some changes will be necessary. The tasks (i.e. what is currently a Runnable in the given implementation) must be converted to a Callable<T>, where T should be substituted with the return-type. The Future<T> returned should then be collected into a list and waited upon on. When all Futures have completed, the result list can be constructed, e.g. through streaming.
With parallelStreams and ForkJoinPool maybe you can get a more straightforward code, plus, an easy way to collect the results of your files after processing. For parallel processing, I prefer to directly use Threads, as a last resort, only when parallelStream can't be used.
boolean doStuff( String file){
// do your magic here
System.out.println( "The file " + file + " has been processed." );
// return the status of the processed file
return true;
}
List<String> jsonFiles = new ArrayList<String>();
jsonFiles.add("file1");
jsonFiles.add("file2");
jsonFiles.add("file3");
...
jsonFiles.add("file200000");
ForkJoinPool forkJoinPool = null;
try {
final int parallelism = 30;
forkJoinPool = new ForkJoinPool(parallelism);
forkJoinPool.submit(() ->
jsonFiles.parallelStream()
.map( jsonFile -> doStuff( jsonFile) )
.collect(Collectors.toList()) // you can collect this to a List<Boolea> results
).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
if (forkJoinPool != null) {
forkJoinPool.shutdown();
}
}
Put your jobs (filenames) into a queue, start 30 threads to process them, then wait until all threads are done. For example:
static ConcurrentLinkedDeque<String> jobQueue = new ConcurrentLinkedDeque<String>();
private static class Worker implements Runnable {
int threadNumber;
public Worker(int threadNumber) {
this.threadNumber = threadNumber;
}
public void run() {
try {
System.out.println("Thread " + threadNumber + " started");
while (true) {
// get the next filename from job queue
String fileName;
try {
fileName = jobQueue.pop();
} catch (NoSuchElementException e) {
// The queue is empty, exit the loop
break;
}
System.out.println("Thread " + threadNumber + " processing file " + fileName);
Thread.sleep(1000); // so something useful here
System.out.println("Thread " + threadNumber + " finished file " + fileName);
}
System.out.println("Thread " + threadNumber + " finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
// Create dummy filenames for testing:
for (int i = 1; i <= 200; i++) {
jobQueue.push("Testfile" + i + ".json");
}
System.out.println("Starting threads");
// Create 30 worker threads
List<Thread> workerThreads = new ArrayList<Thread>();
for (int i = 1; i <= 30; i++) {
Thread thread = new Thread(new Worker(i));
workerThreads.add(thread);
thread.start();
}
// Wait until the threads are all finished
for (Thread thread : workerThreads) {
thread.join();
}
System.out.println("Finished");
}
}
I'm hoping some concurrency experts can advise as I'm not looking to rewrite something that likely exists.
Picture the problem; I have a web connection that comes calling looking for their unique computed result (with a key that they provide in order to retrieve their result) - however the result may not have been computed YET so I would like for the connection to wait (block) for UP TO n seconds before giving up and telling them I don't (yet) have their result (computation time to calculate value is non deterministic). something like;
String getValue (String key)
{
String value = [MISSING_PIECE_OF_PUZZLE].getValueOrTimeout(key, 10, TimeUnit.SECONDS)
if (value == null)
return "Not computed within 10 Seconds";
else
return "Value was computed and was " + value;
}
and then have another thread (the computation threads)that is doing the calculations - something like ;
public void writeValues()
{
....
[MISSING_PIECE_OF_PUZZLE].put(key, computedValue)
}
In this scenario, there are a number of threads working in the background to compute the values that will ultimately be picked up by a web connections. The web connections have NO control or authority over what is computed and when the computations execute - as I've said - this is being done in a pool in the background but these thread can publish when the computation has completed (how they do is the gist of this question). The publish message maybe consumed or not - depending if any subscribers are interested in this computed value.
As these are web connections that will be blocking - i could potentially have 1000s of concurrent connections waiting (subscribing) for their specific computed value so such a solution needs to be very light on blocking resources. The closest i've came to is this SO question which I will explore further but wanted to check i'm not missing something blindly obvious before writing this myself?
I think you should use a Future it gives an ability to compute data in a separate thread and block for the requested time period while waiting for an answer. Notice how it throws an exception if more then 3 seconds passed
public class MyClass {
// Simulates havy work that takes 10 seconds
private static int getValueOrTimeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(10);
return 123;
}
public static void main(String... args) throws InterruptedException, ExecutionException {
Callable<Integer> task = () -> {
Integer val = null;
try {
val = getValueOrTimeout();
} catch (InterruptedException e) {
throw new IllegalStateException("task interrupted", e);
}
return val;
};
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(task);
System.out.println("future done? " + future.isDone());
try {
Integer result = future.get(3, TimeUnit.SECONDS);
System.out.print("Value was computed and was : " + result);
} catch (TimeoutException ex) {
System.out.println("Not computed within 10 Seconds");
}
}
}
After looking in changes in your question I wanted to suggest a different approach using BlockingQueue in such case the producer logic completely separated from the consumer so you could do something like this
public class MyClass {
private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
private static Map<String, String> dataComputed = new ConcurrentHashMap<>();
public static void writeValues(String key) {
Random r = new Random();
try {
// Simulate working for long time
TimeUnit.SECONDS.sleep(r.nextInt(11));
String value = "Hello there fdfsd" + Math.random();
queue.offer(value);
dataComputed.putIfAbsent(key, value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static String getValueOrTimeout(String key) throws InterruptedException {
String result = dataComputed.get(key);
if (result == null) {
result = queue.poll(10, TimeUnit.SECONDS);
}
return result;
}
public static void main(String... args) throws InterruptedException, ExecutionException {
String key = "TheKey";
Thread producer = new Thread(() -> {
writeValues(key);
});
Thread consumer = new Thread(() -> {
try {
String message = getValueOrTimeout(key);
if (message == null) {
System.out.println("No message in 10 seconds");
} else {
System.out.println("The message:" + message);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
consumer.start();
producer.start();
}
}
With that said I have to agree with #earned that making the client thread to wait is not a good approach instead I would suggest using a WebSocket which gives you an ability to push data to the client when it is ready you can find lots of tutorials on WebSocket here is one for example ws tutorial
I have a class that calls a method from another class which uses a thread as it is somewhat a intensive task. The Thread is responsible for looking through a dictionary to find a matching word. When a word is found it should/does set a local variable in that class. I can see that it is successfully setting this String because it say's so in the log. However, whenever I try and retrieve this String from another class and set the TextView to the value of this String, Nothing happens.
I'm using the Thread because a lot of frames were being skipped. However, when I don't use the thread it works as it is suppose to(Minus the frames being skipped).
Here is the method with the thread:
public String checkLetters() {
new Thread(new Runnable() {
#Override
public void run() {
//Finding the directory on SD Card
File sdcard = Environment.getExternalStorageDirectory();
//Retrieve the text file
File file = new File(sdcard,"NewEnglishDictionary.txt");
try {
BufferedReader bufferRead = new BufferedReader(new FileReader(file),24396);
String line; //= "";
//While no word found keep looping
while (wholeWordFound == false ) {
line = bufferRead.readLine();
Log.d("ResolveWord", "Current Line: " + line);
wordReturned = workOutWord(line);
setWord(wordReturned);
}
String value = getWord().toString().toLowerCase();
Log.d("Value of setWord: ", " equals: "+ value);
bufferRead.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
return wordReturned;
}
And calling to retrieve the variable that has been set (according to the log)
tv_WordFound.setText(fixAnagram.getWord());
And the method which is suppose to return it:
public String getWord() {
Log.d("Test", "getWord: " + wordReturned);
return wordReturned;
}
Is there something I'm missing with threads?
Cheers for any help. Logcat itself gives me no clue to where the error lies.
you need to using callback or interface or asynctask for this case. Because your Thread inside checkLetters method will end after your checkLetters. That means if you call getWord() immediately after calling checkLetters, you can only get the previous checking result.
The Memory model of Java does not guarantee, that values set by one thread are immediately visible by another thread.
To guarantee this, you either must declare the variable as "volatile" or have a synchronized involved (e.g. have the getter and setter method with the keyword synchronized).
e.g.
private volatile String word;
or
public synchronized String getWord() { return word; }
public synchronized void setWord(String w) { word = w; }
I m having a server code to process an image.
Now there are n number of requests which tries to execute the code which results in OutOfMemory error or the server to hang and the server goes to not responding state.
To stop the code from executing at once all the requests I m limiting to execute the code one at a time using the below method where i have a variable
if the variable is 10 then wait for the variable to come at 0
if at 0 then set it to 10 then execute the code
run the code and finally set i to 0
The code here -
static newa.Counter cn;
public int getCounta() {
return cn.getCount();
}
public void setCounta(int i) {
cn = new newa.Counter();
cn.setCount(i);
}
at the function i m doing this -
public BufferedImage getScaledImage(byte[] imageBytes)
{
int i=0;
Boolean b = false;
BufferedImage scaledImage = null;
newa.NewClass1 sc = new newa.NewClass1();
try {
sc.getCounta();
} catch (NullPointerException ne) {
sc.setCounta(0);
}
i = sc.getCounta();
if(i==0)
{
sc.setCounta(10);
b = true;
}
else
{
while( b == false)
{
try
{
Thread.sleep(2000);
i = sc.getCounta();
if( i==0)
{
sc.setCounta(10);
b = true;
System.out.println("Out of Loop");
}
} catch (InterruptedException ex) {
System.out.println("getScaledImage Thread exception: " + ex);
}
}
}
..... execute further code
try { } catch { } finally { sc.setCounta(0); }
}
Is there any way I can have this simplified using the Runnable interface or something as I don't know how to do multi-threading.
Forget about the counter and use a synchronized method. Changed your method head to this:
public synchronized BufferedImage getScaledImage(byte[] imageBytes)
This lets all the threads entering the method wait until no other thread is executing the method.
If you want only a small number of threads doing the processing you can use Executor framework to have a thread pool of 10 threads. This will ensure that at one time maximum of 10 threads will be processing the requests.
I am new to Multithreading and synchronization in java. I am trying to achieve a task in which i am given 5 files, each file will be read by one particular thread. Every thread should read one line from file then forward execution to next thread and so on. When all 5 threads read the first line, then again start from thread 1 running line no. 2 of file 1 and so on.
Thread ReadThread1 = new Thread(new ReadFile(0));
Thread ReadThread2 = new Thread(new ReadFile(1));
Thread ReadThread3 = new Thread(new ReadFile(2));
Thread ReadThread4 = new Thread(new ReadFile(3));
Thread ReadThread5 = new Thread(new ReadFile(4));
// starting all the threads
ReadThread1.start();
ReadThread2.start();
ReadThread3.start();
ReadThread4.start();
ReadThread5.start();
and in ReadFile (which implements Runnable, in the run method, i am trying to synchronize on bufferreader object.
BufferedReader br = null;
String sCurrentLine;
String filename="Source/"+files[fileno];
br = new BufferedReader(new FileReader(filename));
synchronized(br)
{
while ((sCurrentLine = br.readLine()) != null) {
int f=fileno+1;
System.out.print("File No."+f);
System.out.println("-->"+sCurrentLine);
br.notifyAll();
// some thing needs to be dine here i guess
}}
Need Help
Though this is not an ideal scenario for using multi-threading but as this is assignment I am putting one solution that works. The threads will execute sequentially and there are few point to note:
Current thread cannot move ahead to read the line in the file until and unless its immediately previous thread is done as they are supposed to read in round-robin fashion.
After current thread is done reading the line it must notify the other thread else that thread will wait forever.
I have tested this code with some files in temp package and it was able to read the lines in round robin fashion. I believe Phaser can also be used to solve this problem.
public class FileReaderRoundRobinNew {
public Object[] locks;
private static class LinePrinterJob implements Runnable {
private final Object currentLock;
private final Object nextLock;
BufferedReader bufferedReader = null;
public LinePrinterJob(String fileToRead, Object currentLock, Object nextLock) {
this.currentLock = currentLock;
this.nextLock = nextLock;
try {
this.bufferedReader = new BufferedReader(new FileReader(fileToRead));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
#Override
public void run() {
/*
* Few points to be noted:
* 1. Current thread cannot move ahead to read the line in the file until and unless its immediately previous thread is done as they are supposed to read in round-robin fashion.
* 2. After current thread is done reading the line it must notify the other thread else that thread will wait forever.
* */
String currentLine;
synchronized(currentLock) {
try {
while ( (currentLine = bufferedReader.readLine()) != null) {
try {
currentLock.wait();
System.out.println(currentLine);
}
catch(InterruptedException e) {}
synchronized(nextLock) {
nextLock.notify();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
synchronized(nextLock) {
nextLock.notify(); /// Ensures all threads exit at the end
}
}
}
public FileReaderRoundRobinNew(int numberOfFilesToRead) {
locks = new Object[numberOfFilesToRead];
int i;
String fileLocation = "src/temp/";
//Initialize lock instances in array.
for(i = 0; i < numberOfFilesToRead; ++i) locks[i] = new Object();
//Create threads
int j;
for(j=0; j<(numberOfFilesToRead-1); j++ ){
Thread linePrinterThread = new Thread(new LinePrinterJob(fileLocation + "Temp" + j,locks[j],locks[j+1]));
linePrinterThread.start();
}
Thread lastLinePrinterThread = new Thread(new LinePrinterJob(fileLocation + "Temp" + j,locks[numberOfFilesToRead-1],locks[0]));
lastLinePrinterThread.start();
}
public void startPrinting() {
synchronized (locks[0]) {
locks[0].notify();
}
}
public static void main(String[] args) {
FileReaderRoundRobinNew fileReaderRoundRobin = new FileReaderRoundRobinNew(4);
fileReaderRoundRobin.startPrinting();
}
}
If the only objective is to read the files in round-robin fashion and not strictly in same order then we can also use Phaser. In this case the order in which files are read is not always same, for example if we have four files (F1, F2, F3 and F4) then in first phase it can read them as F1-F2-F3-F4 but in next one it can read them as F2-F1-F4-F3. I am still putting this solution for sake of completion.
public class FileReaderRoundRobinUsingPhaser {
final List<Runnable> tasks = new ArrayList<>();
final int numberOfLinesToRead;
private static class LinePrinterJob implements Runnable {
private BufferedReader bufferedReader;
public LinePrinterJob(BufferedReader bufferedReader) {
this.bufferedReader = bufferedReader;
}
#Override
public void run() {
String currentLine;
try {
currentLine = bufferedReader.readLine();
System.out.println(currentLine);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public FileReaderRoundRobinUsingPhaser(int numberOfFilesToRead, int numberOfLinesToRead) {
this.numberOfLinesToRead = numberOfLinesToRead;
String fileLocation = "src/temp/";
for(int j=0; j<(numberOfFilesToRead-1); j++ ){
try {
tasks.add(new LinePrinterJob(new BufferedReader(new FileReader(fileLocation + "Temp" + j))));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
public void startPrinting( ) {
final Phaser phaser = new Phaser(1){
#Override
protected boolean onAdvance(int phase, int registeredParties) {
System.out.println("Phase Number: " + phase +" Registeres parties: " + getRegisteredParties() + " Arrived: " + getArrivedParties());
return ( phase >= numberOfLinesToRead || registeredParties == 0);
}
};
for(Runnable task : tasks) {
phaser.register();
new Thread(() -> {
do {
phaser.arriveAndAwaitAdvance();
task.run();
} while(!phaser.isTerminated());
}).start();
}
phaser.arriveAndDeregister();
}
public static void main(String[] args) {
FileReaderRoundRobinUsingPhaser fileReaderRoundRobin = new FileReaderRoundRobinUsingPhaser(4, 4);
fileReaderRoundRobin.startPrinting();
// Files will be accessed in round robin fashion but not exactly in same order always. For example it can read 4 files as 1234 then 1342 or 1243 etc.
}
}
The above example can be modified as per exact requirement. Here the constructor of FileReaderRoundRobinUsingPhaser takes the number of files and number of lines to read from each file. Also the boundary conditions need to be taken into consideration.
You are missing many parts of the puzzle:
you attempt to synchronize on an object local to each thread. This can have no effect and the JVM may even remove the whole locking operation;
you execute notifyAll without a matching wait;
the missing wait must be at the top of the run method, not at the bottom as you indicate.
Altogether, I'm afraid that fixing your code at this point is beyond the scope of one StackOverflow answer. My suggestion is to first familiarize yourself with the core concepts: the semantics of locks in Java, how they interoperate with wait and notify, and the precise semantics of those methods. An Oracle tutorial on the subject would be a nice start.