I have a class that basically has two methods the first one takes a String (name of a file) and a thread:
public static void readFile(String s, Thread t){
Runnable read = new Runnable() {
public void run() {
//SOME CODE
}
t = new Thread(read);
t.start();
}
The second method is a main method that asks the user for input and then uses that input to set a few things (like if the number of threads is just one or if it is equal to the number of objects in a list).
public static void main(String[] args){
//SOME CODE
for(Object x: ListOfObjects){
//t1 is the same thread each time if one thread requested, otherwise t1 is a different thread each time
readFromFile(textFileString, t1);
//SOME CODE
}
If the user were to request 5 threads (for 5 items in a list), how could the above be modified for that? Currently, my main method has a loop (for the number of items in the list) and then the first method is called for each iteration in the loop. Is there a way to take the number of threads requested by the user, and initiate/start them in the first method all at once instead of one at a time and calling the method?
Implement the Runnable interface. I tried
this and it seems to work:
class StringThread implements Runnable
{
private String str;
private int num;
StringThread(String s, int n)
{
str = new String (s);
num =n;
}
public void run ( )
{
for (int i=1; i<=num; i++)
System.out.print ("THREAD NAMED: " + str+" I IS: " +
i + "\n");
}
}
//IN the main program:
StringThread t1 = new StringThread ("THR-1",100);
new Thread(t1). start ( );
StringThread t2 = new StringThread ("THR-2",200);
new Thread(t2). start ( );
Related
I would like to create a program like this:
I start in my main 10 threads like this (My class implements runnable)
public class Main {
public static void main(String[] ar) {
for (int i = 1; i <= 5; i++) {
Count1by1 count1by1 = new Count1by1(i);
Thread myThread = new Thread(count1by1);
myThread.start();
}
}
}
and I want to create a critical section that if the thread enters it can count to 10, if not it will wait().
I've tried many implementations but is not working (cuz every threads count to 10 without waiting...
This is the class
public class Count1by1 implements Runnable{
private int threadnumber;
private Object mutex = new Object();
public Count1by1(int num) {
this.threadnumber=num;
//this.mutex= new Object();
}
public void count() {
synchronized (mutex) {
for (int i = 1; i <= 10; i++) {
System.out.println("#"+threadnumber + " counts: " + i);
try {
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e);
}
}
}
}
#Override
public void run() {
count();
}
}
private Object mutex = new Object();
Okay. You create a new object. It has no name (because objects do not have names). You also created a field (which isn't an object; it's a pointer to one). It currently points at the new object you made.
Each of the 10 instances of Count1by1 has a field, and each points to a unique object, given that they all run new Object().
synchronized (mutex) {
Okay, this takes the field mutex follows what its pointing at, finds the object there, and then locks on that. Given that there are 10 unique objects (each Count1by1 instance has its own object), this accomplishes nothing. To have a mutex, at least 2 threads need to lock on the same object.
Solution
Make the lock object in your main and pass it to your threads:
private final Object mutex;
public Count1by1(int num, Object mutex) {
this.threadnumber=num;
this.mutex = mutex;
}
Now there's one mutex object (hint: Count the number of times the code executes a new statement, that's how many you have). Each of your 10 instances of Count1by1 has its own field, but they are all pointing at the same object (it's like 10 people having a piece of paper with the same home address written on it: 10 'variables', just one house), hence, synchronizing on them will do something.
I'm having a difficult time understanding how to synchronise an ArrayList over two threads. Basically, I want one thread appending objects to the list and the other one reading from that list at the same time.
Here is the class that deploys the threads:
public class Main {
public static ArrayList<Good> goodList = new ArrayList();
public static void main(String[] args) {
Thread thread1 = new Thread(new GoodCreator());
Thread thread2 = new Thread(new WeightCounter());
thread1.start();
thread2.start();
}
}
Then the two Runnable classes:
This one reads lines of two values from a text file and appends new objects.
public class GoodCreator implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
private static Scanner scan;
#Override
public void run() {
System.out.println("Thread 1 started");
int objCount = 0;
try {
scan = new Scanner(new File(System.getProperty("user.home") + "//Goods.txt"));
} catch (FileNotFoundException e) {
System.out.println("File not found!");
e.printStackTrace();
}
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] words = line.split("\\s+");
synchronized(goodList){
goodList.add(new Good(Integer.parseInt(words[0]), Integer.parseInt(words[1])));
objCount++;
}
if(objCount % 200 == 0) System.out.println("created " + objCount + " objects");
}
}
}
This iterates over the arraylist and is supposed to sum up one of the fields.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
No matter the input, weightSum never gets incremented and stays 0
Thread 1 started
Thread 2 started
0
Any help is much appreciated
You are running two independently running threads. These thread can run in any order and if one stop e.g. to read from a file, the other thread doesn't assume it has to wait for it.
In short, your second thread completes before the first thread has added anything to the list.
There is no good fix as this is not a good example of why you would use multiple threads, however to get an outcome what you can do is this.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
throw AssertionError(ie);
}
int weightSum = 0;
synchronized(goodList){
for (Good g : goodList)
weightSum += g.getWeight();
}
System.out.println(weightSum);
}
}
}
This will print the sum 10 times, 0.1 seconds apart. Depending on how long your file takes to load you will be able to see the sum for what has loaded so far.
This is something called a producer-consumer task. You can do it with arraylist, but it's honestly just not the right way to approach this problem.
Luckily, Java provides us with some collections, the BlockingQueue collections, which are designed specifically for this reason;
//the collection with the stuff in it
static BlockingQueue<Object> items = new BlockingQueue<Object>();
//(there are a few different types of blocking queues, check javadocs.
//you would want Linked or Array blocking queue
//what happens on the reader thread
public void producer()
{
//read the data into the collection
for (all the data in the file)
{
//add the next item
items.put(/* next item from file or w/e */);
//stop if necessary
if (atEndOfFile) stillReadingData = false;
//etc
}
}
Now you need to read the data out of the queue - luckily this is easy enough;
//what happens on the other threads
public void consumer()
{
//keep this thread alive so long as there is data to process
//or so long as there might be more data to process
while (stillReadingData || !items.isEmpty())
{
//get the next item from the list
//while the list is empty, we basically sleep for "timeout" timeunits,
//then the while-loop would repeat, and so on
Object o = items.poll(long timeout, int units);
if (o != null) //process it
}
}
In this way, you can continuously add items to the queue with the producer thread, and the items will be processed as soon as a consumer thread is free (this approach scales well with lots of consumer threads). If you still need a collection for the items, then you should make a second collection and add them to that after they have been processed.
As a side note, you may still need to synchronize oprations which occur while processing the items. For example, you would need to synchronize increments on "weightSum" (or alternately use AtomicInteger).
Try this change in the WeightCounter class.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
while(goodList.isEmpty()) {
Thread.sleep(1000);
}
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
This change will cause the WeightCounter thread to wait for the other thread to finish populating the goodList with data before attempting to read from it.
I am using a simple thread pool to read in a large dictionary I have written a for loop that loops through the whole dictionary (10000 words), I have tried to get it so it stores every 500 into a thread assigning that sub arraylist to a single thread to handle.
When there are 500 words within the arraylist it then stores it within an instance of a class 'Words'. This simply stores and allows access to an arrayList (the arrayList assigned to that thread).
This doesnt appear to be working as there are duplicates and most the time the last 500 words in the dictionary are what all the threads end up using which I find strange. In addition I also noticed when I add in a simple timeout for 3 seconds at the end of the inside of that for loop shown below it works however this seems like a horrible fix and I want this program to be as efficent and fast as possible.
// Executor Program
ExecutorService executor = Executors.newFixedThreadPool(cores);
ArrayList<String> words123 = new ArrayList<String>();
for (int i = 0; i < dictionary.size(); i++) {
words123.add(dictionary.get(i));
if(words123.size() == 1000) {
Words wordsList = new Words(words123);
Runnable worker = new WorkerThread(wordsList, passwords, stp);
executor.execute(worker);
words123 = new ArrayList<String>();
}
}
executor.shutdown();
//wait for all jobs to complete
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
// WORD OBJECT ------------------
public class Words {
public static ArrayList<String> words = new ArrayList<String>();
public Words(ArrayList words) {
this.words = words;
}
public int getSize() {
return words.size();
}
public String getWord(int i) {
return words.get(i);
}
}
//WORKER THREAD ----------------
public static Words wordList;
public static int cmd;
public static HashMap<String, String> passwords = new HashMap<String, String>();
public static SimpleThreadPool stp;
/**
* Constructor
* #param s
*/
public WorkerThread(Words word, HashMap passwords, SimpleThreadPool stp, int cmd){
this.wordList = word;
//System.out.println("in " + words);
//Read in hashes using readFromFile method
this.passwords = passwords;
this.stp = stp;
this.cmd = cmd;
}
/**
* For a thread pool to function, ensure that the run() method terminates
* This method prints out the command, calls a function, then prints end and terminates
*/
#Override
public void run() {
//System.out.println(Thread.currentThread().getName()+" Start.");
//System.out.println("WOOOO " + wordList.getWords() + cmd);
for(int i = 0; i < wordList.getSize(); i++){
Password pass = new Password(wordList.getWord(i), hashPassword(wordList.getWord(i)));
//System.out.println(pass.getOriginalPass());
//checkHash(pass);
// Check password with letter-number edits (e.g. a-->#)
letterSymbolEdit(pass);
// Check password with capital letter edits
//capitalsEdit(pass);
// Reverse password
reverseEdit(pass);
// Concatenate all words in dictionary
//concatEdit(pass);
printPermutations(pass);
// All possible numbers generated and appended to string
for(int j = 0; j < 4; j++){
numberBuilder("", 0, j, pass);
}
}
//System.out.println(Thread.currentThread().getName()+" End.");
}
The issue is that the 'words' variable in the Words class is static, that means that every instance of that class is using the same list.
Also, since you're trying to get efficient, I would use a different approach. Instead of
ExecutorService executor = Executors.newFixedThreadPool(cores);
use
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(cores, cores, 0L, TimeUnit.MILLISECONDS, workQueue);
executor.prestartAllCoreThreads();
and then add Runnable instances directly to the workQueue. In this way you don't have to wait to divide words among threads yourself: threads will fetch them as soon as they complete a task.
i must say i am a beginner in Java.
I use Eclipse. I want to accomplish the following scenario and couldn't find how to do it:
While a java program runs it outputs text to the console, i also want to be able to input text and process it without blocking the output by waiting for input.
Assume this:
-Thread 1 outputs a number to the console every second
-Thread 2 listens for input
(The code is a mockup)
//**Thread 1:**
int incrementBy = 0;
for (int i = 0; i < 1000; i++) {
i = i + incrementBy;
//Pause for 1 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print text
System.out.println(i);
}
//**Thread 2:**
String myIncrement = System.console().readLine();
(Now process the input and change the incrementBy var in Thread 1)
Right now in my program i am using 1 thread for input and another one for output. But i can easily change the design.
All i could find was something about server and client, i would like to keep my code in one place-package. And i currently don't know how to make a GUI with a text box for output and one for input.
Can you recommend something please?
SOLVED - it turns out I am VERY VERY new to JAVA.
It seems that java allows the user to input text while another thread outputs to the console.
This is the reason why i couldn't find anything in my searches for things like "java input and output to console asynchronous". I had a problem in my input code exactly where i was asking for input and because i knew from single threaded programs that the program halts until i enter the text and press enter i assumed that the error was thrown because the output thread was taking over the console and terminating the input thread.
Here is my code for those who search (Take it as a guide, might not work if compiled):
//Main app
public class textInpuOutputManager {
//here we create the two threads (objects that implement the runnable interface)
static TextInputObject ti;
static TextOutputObject to;
public static void main(String[] args) {
//we instantiate the objects
ti = new TextInputObject();
to = new TextOutputObject();
//we call the start method to start the threads for input and output
ti.start();
to.start();
}
}
//TextInputObject class
public class TextInputObject implements Runnable {
//Method that gets called when the object is instantiated
public TextInputObject() {
System.out.println("Created TextInputObject");
}
//create a thread object and check if it's not already created
static Thread thread;
//This method gets called from the main
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
//this method gets called by the thread.start(); from above
#
Override
public void run() {
System.out.println("Text input thread created and now it runs");
readTextFromConsole();
}
Scanner inputReader = new Scanner(System.in);
//check for input all the time - THIS WILL NOT HALT THE PROGRAM
public void readTextFromConsole() {
System.out.println("Enter something:");
String myinput = inputReader.nextLine();
System.out.println("You Entered: " + myinput);
readTextFromConsole();
}
}
//TextOutputObject
public class TextOutputObject implements Runnable {
//Method that gets called when the object is instantiated
public TextOutputObject() {
System.out.println("Created TextOutputObject");
}
static Thread thread;
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
#
Override
public void run() {
System.out.println("Text output thread created and now it runs");
//Make it output text every 4 seconds to test if you can input text while it's used for output
for (int i = 0; i < 100; i++) {
//Pause for 4 seconds
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print i to console
System.out.println(i);
}
}
}
Also BIG thank you for all of you who took the time to respond
I'm not sure exactly what it is you want to do, but if you're new and you don't know how to make guis, I would try a JOptionPane
String input = JOptionPane.showInputDialog("User input is returned as a string; use Integer.parseInt(input) to retrieve an integer from this method");
You could make two inner classes and implement Runnable in both of them.
import java.util.Scanner;
public class Test{
private Thread t1;
private Thread t2;
public static void main(String[] args){
new Test();
}
private class TOne implements Runnable{
public void run(){
int incrementBy = 0;
for (int i = 0; i < 1000; i++) {
i = i + incrementBy;
//Pause for 1 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print text
System.out.println(i);
}
}
}
private class TTwo implements Runnable{
public void run(){//Code for Thread 2
try{
Scanner scr = new Scanner(System.in);
System.out.println(scr.next());
}catch(Exception ex){
ex.printStackTrace();
}
}
}
public Test(){
t1 = new Thread(new TOne());
t1.run();
t2 = new Thread(new TTwo());
t2.run();
}
}
Not the most elegant way, and it doesn't work flawlessly. You'd have to tinker with the second Thread a little more. For information on how GUI etc. work you should check the Swing library. Googling it should work just fine.
Some important keywords for you wpuld be:
JFrame, JPanel, LayoutManager, JTextArea, JTextField, JButton, ActionListener, Inner Class
I posted yesterday about this but my code was messy. What I'm looking to do is count the number of lines of two separate files and print the line number in a separate thread for each file.
This is what i have:
import java.io.File;
import java.util.Scanner;
public class fileReader implements Runnable
{
static int count = 0;
static int count1 = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest1.txt"));
Scanner file2 = new Scanner(new File("filetest2.txt"));
while (file1.hasNextLine())
{
count++;
file1.nextLine();
}
while (file2.hasNextLine())
{
count1++;
file2.nextLine();
}
}
catch(Exception e)
{
count = -1;
count1 = -1;
}
}
public static void main(String[] args)
{
(new Thread(new fileReader())).start();
System.out.println("File one has " + count + " lines");
System.out.println("File two has " + count1 + " lines");
}
}
The problem is that it does not work. Can someone point me in the right direction? Thanks.
You are on the right track using Runnable. You have a couple problems right now:
You currently create 1 fileReader with 1 thread for both files, but your intent is to have a separate thread for each.
You are trying to communicate between threads using some static variables, but you're not waiting for the worker thread to be done before printing the variables.
To solve your first problem, you need to create a new Runnable and a new thread for each file. (I'm going to rename your fileReader class to LineCounter to avoid confusion with the similarly named FileReader from the standard library).
class LineCounter implements Runnable {
private final File file;
public LineCounter(File file) {
this.file = file;
}
public void run() {
// Count lines in file.
}
}
Now you can create 2 separate LineCounter objects, one to count the lines in each file.
Thread thread1 = new Thread(new LineCounter(new File("filetest1.txt")));
Thread thread2 = new Thread(new LineCounter(new File("filetest2.txt")));
thread1.start();
thread2.start();
As for your second problem, your main thread must (the one that spawned off these two other threads) needs to wait for them to complete before reading the variables holding the number of lines in each file. You can instruct your main thread to wait for the another thread to complete by using join()
thread1.join();
thread2.join();
// Print your variables.
That being said, communicating between threads with static variables is dubious at best:
To really do this right, you'd have to either synchronize access to those variables, or else declare them as volatile.
When programming with threads, it's preferable to share as little state (variables) as possible with other threads.
Further, there exists the very convenient Executor framework which presents a nicer API for dealing with threads. One big win is that is allows you to easily return a value from a thread, which you could use to return the number of lines read.
The big changes are:
Your class implements Callable<Integer> instead of Runnable. The <Integer> part here means you want your thread to return an Integer (i.e. the number of lines in the file)
Instead of void run(), you define Integer call(), which returns the number of lines in the file.
Instead of creating Threads directly, you submit tasks to be done to an Executor.
Instead of join()ing threads together, simply get() the return value of a thread from a Future.
Converted to Executor style, the solution is something like
class LineCounter implements Callable<Integer> {
private final File file;
public LineCounter(File file) {
this.file = file;
}
public Integer call() {
// Count number of lines in file.
return numLines;
}
}
And in your main thread:
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> future1 = executor.submit(new LineCounter(new File("file1.txt")));
Future<Integer> future2 = executor.submit(new LineCounter(new File("file2.txt")));
Integer file1Lines = future1.get();
Integer file2Lines = future2.get();
You need to wait for the thread to finish its job.
You print your resault too early.
thr.join() blocks your program until thr finishes.
public static void main(String args[]) {
try {
Thread thr = new Thread(new fileReader());
thr.start();
thr.join();
System.out.println("File one has " + count + " lines");
System.out.println("File two has " + count1 + " lines");
} catch (InterruptedException ex) {
Logger.getLogger(fileReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class fileReader1 implements Runnable
{
static int count = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest1.txt"));
............
............
............
}
}
public class fileReader2 implements Runnable
{
static int count = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest2.txt"));
............
............
............
}
}
Now you can start two threads and start reading the files simultaneously:
Thread t1=new Thread(new fileReader1());
Thread t2=new Thread(new fileReader2());
t1.start();
t2.start();