import java.util.Scanner;
public class ThreadClass{
public static void main(String[] args)
{
System.out.println("Enter the characters, Press Enter to begin");
System.out.println("The quick brown fox jumps over the lazy dog");
Scanner sc=new Scanner(System.in);
String scr= sc.nextLine();
MyThread tr=new MyThread();
try {
tr.sleep(11000);
System.out.println("Time Over");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class MyThread extends Thread{
public void run()
{
System.out.println("Time over");
ThreadClass tc=new ThreadClass();
String str=tc.scr;
if(str.equals("The quick brown fox jumps over the lazy dog"))
{
System.out.println("Successfully completed");
}
else
{
System.out.println("The typed Words do not match");
}
}
}
I am trying to make an application that prompts the user to type a string within 11 seconds. To accomplish this I have two classes namely ThreadClass and MyThread. In Thread class I have defined methods to take input from the user and to set the timer to 10 seconds. In MyThread class I have defined methods for post thread completion i.e. what the program will do after the time is over. I want to add a feature in MyThread class so that it compares the user input with the string provided. The problem is that when I try to access the String variable scr, defined in ThreadClass from MyThread class by creating an it gives me an error. Even if I try to extend ThreadClass from MyThread class it gives me an error. Also declaring scr as static gives me the same result. Is there any possible way to use scr variable in MyThread?
I had while ago same issue, i used Concurrency API from java, and it works without problem
here is solution for your problem
public class ThreadClass {
public static void main(String[] args) {
final ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
System.out
.println("Enter the characters, Press Enter to begin");
System.out
.println("The quick brown fox jumps over the lazy dog");
Scanner sc = new Scanner(System.in);
return sc.nextLine();
}
});
try {
String str = future.get(11, TimeUnit.SECONDS);
System.out.println("Your string " + str);
} catch (TimeoutException | InterruptedException | ExecutionException e) {
future.cancel(true);
System.out.println("Time Over");
}
}
}
You didn't tell us what the error message is, but I can guess.
ThreadClass tc=new ThreadClass();
String str=tc.scr;
There is no instance variable named scr in your ThreadClass class. There is only a local variable with that name in your main() routine.
If you do not yet understand the difference between local variables, instance variables (a.k.a., "fields") and class variables (a.k.a., "static variables"), then it might be a little bit early for you to be trying to understand threads.
Related
I am working on a console based Java application. I've to show suggestions to user for selecting a database. I am using Scanner for reading input and a separate thread for checking if input contains TAB in order to print the suggestions.
UPDATE
As per below answer, I added synchronized block to code and the Exception is gone. However, I don't see any suggestions printed on the console. Below is my current code:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Test {
private static List<String> suggestions = new ArrayList<>();
private static final Object lock = new Object();
public static void main(String[] arguments) {
suggestions.add("H2");
suggestions.add("Mongo");
suggestions.add("MySQL");
suggestions.add("Oracle");
suggestions.add("PostgreSQL");
suggestions.add("SQLite");
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a database name, press TAB for suggestions");
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (lock) {
if (scanner.hasNext()) {
String input = scanner.next();
if (input.contains("\\t")) {
System.out.println(getSuggestions(input));
}
}
}
}
}
}).start();
synchronized (lock) {
String selectedDatabase = scanner.nextLine();
System.out.println(selectedDatabase);
}
}
private static List<String> getSuggestions(String input) {
List<String> possibleSuggestions = new ArrayList<>();
for (String suggestion : suggestions) {
if (suggestion.startsWith(input)) {
possibleSuggestions.add(suggestion);
}
}
return possibleSuggestions;
}
}
Could somebody please help?
Simply put, Scanner is not a thread-safe class and you are using it in two different threads.
You instantiate the scanner it in the Main thread and use it in the other one. In the background the constructor of Scanner might have initialized fields that are not necessarily synced to the other thread.
And while the other thread runs you do a scanner.nextLine() in the Main thread which might execute at the exact same time as the other thread doing a scanner.hasNext(), leading to concurrent access.
You need a way to synchronize access to the scanner (everywhere), e.g. by means of a lock.
synchronized (lock) {
if (scanner.hasNext()) {
String input = scanner.next();
if (input.contains("\\t")) {
System.out.println("ok");
}
}
}
where the lock is a static field you synchronize on:
private static final Object lock = new Object();
Doing a threading problem and I am not sure if this is how its supposed to be or if I coded incorrectly. From what I understand, threading should have multiple methods going at the same time and because of this they should be intertwined. My code is supposed to take a single char and repeat 1000 times but instead of having different variations of the two letters it goes "a" a thousand times, then "b" a thousand times. What is my issue?
Main Method
import java.util.*;
public class MainThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner answer = new Scanner(System.in);
System.out.println("Give me a single character: ");
char h = answer.next().charAt(0);
System.out.println("Give me another single character: ");
char a = answer.next().charAt(0);
MyThread t1 = new MyThread(h);
MyThread t2 = new MyThread(a);
t1.start(h);
t2.start(a);
answer.close();
}
}
my Threading class
import java.util.*;
public class MyThread extends Thread{
Scanner answer = new Scanner(System.in);
public MyThread(char x) {
// TODO Auto-generated constructor stub
}
public void Stored(char x){
System.out.println("Type a single letter here: ");
}
//modified run method
public void start(char x){
for(int i = 0; i < 1000; i++){
System.out.print(x);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
}
}
What you have done is NOT multithreading, rather you have called the start method sequentially, i.e., in order to run the multiple threads parallelly, you need to override the run() method in your MyThread class.
The important point is that run() method will be called by JVM automatically when you start the Thread, and the code inside run() will be executed in parallel with the main/other threads, so override run() inside MyThread class as shown below:
class MyThread extends Thread {
private char x;
public MyThread(char x) {
this.x= x;
}
// Add run() method
public void run() {
for (int i = 0; i < 10; i++) {
System.out.print(x);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
}
}
MainThread class:
public class MainThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner answer = new Scanner(System.in);
System.out.println("Give me a single character: ");
char h = answer.next().charAt(0);
System.out.println("Give me another single character: ");
char a = answer.next().charAt(0);
MyThread t1 = new MyThread(h);
MyThread t2 = new MyThread(a);
t1.start();//this calls run() of t1 automatically
t2.start();//this calls run() of t2 automatically
answer.close();
}
}
I suggest you have a look here for basic understanding on how to create and start the Thread and how multi-threading works.
In order to let the threads run in parallel, the run method needs to be implemented instead of start.
See the JavaDoc for Thread.start():
Causes this thread to begin execution; the Java Virtual Machine calls
the run method of this thread.
The result is that two threads are running concurrently: the current
thread (which returns from the call to the start method) and the
other thread (which executes its run method).
First of all, it's not guaranteed that your described behavior will never occur, even when you implement a correct multithreading. But, it shouldn't be repeatable ;)
The solution is: don't override the start() but the run() method.
The thread constructor should take the argument, the start() is called (and no new start method with an argument!) from the main, and the run() implements the job that is executed parallel. Therefore, you can access the thread's field which you set in your thread constructor.
The error was already explained: the start method is being overridden instead of the run method. Anyway it is not recommended to extend the Thread class since you are not wanting to extend its functionality.
You just want to use a Thread, so a better approach (IMO) is to provide a Runnable to the Thread:
public static void main(String[] args) {
// ...
Thread t1 = new Thread(new MyRunnable(h));
t1.start();
}
The Runnable (use a better Name in production code):
public class MyRunnable implements Runnable {
private final char ch;
public MyRunnable(char theChar) {
ch = theChar;
}
#Override
public void run() {
for (int i = 0; i < 1000; i++) {
...
}
}
This could be improved using with Lambda, but is not the point here
More: "implements Runnable" vs. "extends Thread"
I am trying to implement threads where one thread generates a random number while another thread waits once it generates random number it should notify and wait for the other thread to do the same. I am getting illegal monitor state exception, please help me out and point out my mistake
class Dice
{
int diceValue;
public Dice()
{
this.diceValue=0;
}
}
public class DiceGame implements Runnable
{
Dice d;
public DiceGame()
{
this.d=new Dice();
}
public void run()
{
if(Thread.currentThread().getName().equals("Player 1"))
{
Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+" dice Value is "+d.diceValue);
d.notifyAll();
try
{
d.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
else if(Thread.currentThread().getName().equals("Player 2"))
{
Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
try
{
d.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+"dice Value is ");
d.notifyAll();
}
}
}
}
public static void main(String []args)
{
DiceGame dg=new DiceGame();
Thread tr1=new Thread(dg);
Thread tr2=new Thread(dg);
tr1.setName("Player 1");
tr2.setName("Player 2");
tr1.start();
tr2.start();
}
}
synchronized(d)
{
try
{
d.wait();
Any time you see an unconditional call to wait, you know there's a bug right there. Before you wait, you have to make sure the thing you're waiting for didn't already happen. That's the reason you entered synchronized a block, right?
The whole point of the wait/notify mechanism is that you can atomically release a lock and await notification. That can't possibly work if you don't check the predicate (the thing that you're waiting for) before calling wait.
Here synchronized block is necessary to hold the monitor when calling wait.
Right, because unless you're inside a synchronized block, there's no way you can tell whether the thing you're waiting for has already happened or not. And since you must check whether it's already happened before you wait for it, you can only call wait from inside a synchronized block. But you didn't check! You understand the requirement but not its rationale, so you formally met it, but still managed to create the very problem the requirement is designed to prevent!
I guess, the problem is that you are notifying every other thread before waiting youself.
d.notifyAll();
try
{
d.wait();
}
Refer to this post: https://stackoverflow.com/a/828341/5602214
Your code could be improved in several ways, but with a few little hacks it can work:
class Dice
{
int diceValue;
public Dice()
{
this.diceValue=0;
}
}
public class DiceGame implements Runnable
{
Dice d;
public DiceGame()
{
this.d=new Dice();
}
#Override
public void run()
{
if(Thread.currentThread().getName().equals("Player 1"))
{
final Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+" dice Value is "+d.diceValue);
d.notifyAll();
try
{
d.wait();
}
catch (final InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
else if(Thread.currentThread().getName().equals("Player 2"))
{
final Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
try
{
d.wait();
}
catch (final InterruptedException e)
{
e.printStackTrace();
}
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+" dice Value is "+d.diceValue);
d.notifyAll();
}
}
}
}
public static void main(final String []args) throws InterruptedException
{
final DiceGame dg=new DiceGame();
final Thread tr1=new Thread(dg);
final Thread tr2=new Thread(dg);
tr1.setName("Player 1");
tr2.setName("Player 2");
tr2.start();
Thread.sleep(100);
tr1.start();
}
}
I got no illegalMonitorstate exception, but the first thread get locked up forever. Basically the problem is that the first thread rolls the dice, and calls d.notifyAll before actually the 2nd thread could start and waiting for the dice. This is naively solved by first starting thread 2 then waiting a bit and start thread 1.
You might also consider:
using the Java convention for braces { }
rg.nextInt gives values between 0..5, not 1..6
it is bad idea to make the thread code work differently depending on the name of the thread. In OOP different behavior is expressed with descendant classes instead.
I guess you're wishing for an universal solution for rolling the dice with multiple players. This problem is not necessarily a problem which requires concurrent programming, since rolling the dice goes serially amongst players. You can of course have the players as Threads, but only one Thread will be active at any point of time. In case of using Threads, you shall implement your own scheduling logic which ensures consistent one-after-another scheduling of threads. Using a monitor (e.g. synchornize(d)) does not offer any guarantee of the ordering, it is only built to guarantee that up to one thread can access to the dice at any point in time.
A solution with any number of players but no threads (this is not a concurrency problem after all) shows this behavior:
import java.util.Random;
class Dice {
private final Random rg=new Random();
private int diceValue=1;
public void roll() {
diceValue=rg.nextInt(6)+1;
}
#Override
public String toString() {
return "value="+diceValue;
}
}
public class Player extends Thread {
Dice dice;
int rollsLeft=6;
public Player(final Dice dice) {
this.dice=dice;
}
#Override
public void run() {
while (rollsLeft>0) {
synchronized(dice) {
// dice obtained
dice.roll();
System.out.println(Thread.currentThread().getName()+" rolled "+dice);
}
// dice released
rollsLeft--;
// just wait a little to make it slower and let other threads to join
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
// ignore
}
}
}
public static void main(final String []args) throws InterruptedException {
final Dice dice=new Dice();
final Player player1=new Player(dice);
final Player player2=new Player(dice);
player1.start();
player2.start();
}
}
Which gives:
Thread-0 rolled value=1
Thread-1 rolled value=6
Thread-0 rolled value=2
Thread-0 rolled value=4
Thread-1 rolled value=2
etc...
As you can see, the order (i.e. player1, player2, player1, player2) is not guaranteed.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class Dice {
private final Random rg=new Random();
private int diceValue=1;
public void roll() {
diceValue=rg.nextInt(6)+1;
}
#Override
public String toString() {
return "value="+diceValue;
}
}
public class Player {
Dice dice;
String player;
public Player(final Dice dice,final String player) {
this.dice=dice;
this.player=player;
}
public void roll() {
dice.roll();
System.out.println(player+" rolled "+dice);
}
public static void main(final String []args) throws InterruptedException {
final Dice dice=new Dice();
final List<Player> players=new ArrayList<Player>();
players.add(new Player(dice,"Ann"));
players.add(new Player(dice,"Ben"));
players.add(new Player(dice,"Cecil"));
players.add(new Player(dice,"Denise"));
for (int rounds=0;rounds<6;rounds++) {
System.out.println("---");
for (final Player player:players) {
player.roll();
}
}
}
}
Which gives you the expected output, i.e. Ann, Ben, Cecil, Denise has 6 rounds of rolling the dice.
I just want to start and stop the thread when return key is pressed.
Here thread is stopped fine but i cant Start that thread again please help.
Also explain me the use of volatile keyword .Is it helpful for me to over come this problem.
public class Sync extends Thread{
public boolean meth= true;
public void run(){
while(meth){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
public void shutdown(){
meth=false;
}
public void startup(){
meth=true;
}
}
MAIN CLASS``
package com.Sync;
import java.util.Scanner;
public class SyncMain {
public static void main(String[] arg) throws InterruptedException{
Sync hi= new Sync();
hi.start();
System.out.println("press enter to stop");
Scanner d= new Scanner(System.in);
d.nextLine();
hi.shutdown();
System.out.println("press enter to start");
d.nextLine();
hi.startup();
}
}
OUTPUT
run:
press enter to stop
hello
hello
hello
hello
press enter to start
BUILD SUCCESSFUL (total time: 6 seconds)
Thread's are not re-entrant, that is, once they exit the run method, they can't be restarted, you need to create a new instance.
One solution would be to create a new instance of Sync and start it, but a better solution, based on you code might, be to use a wait lock to "pause" the thread and the allow it to resume, for example...
public static class Sync implements Runnable {
private AtomicBoolean keepRunning = new AtomicBoolean(true);
private AtomicBoolean pause = new AtomicBoolean(false);
private ReentrantLock lckPause = new ReentrantLock();
private Condition conPause = lckPause.newCondition();
public void run() {
while (keepRunning.get() && !Thread.currentThread().isInterrupted()) {
while (pause.get() && !Thread.currentThread().isInterrupted()) {
lckPause.lock();
try {
System.out.println("Paused");
conPause.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
lckPause.unlock();
}
}
if (!Thread.currentThread().isInterrupted()) {
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
}
public void setPaused(boolean paused) {
if (pause.get() != paused) {
pause.set(paused);
if (!paused) {
lckPause.lock();
try {
conPause.signal();
} finally {
lckPause.unlock();
}
}
}
}
public void terminate() {
keepRunning.set(false);
setPaused(false);
}
}
This basically sets up two loops, one to keep the thread running until it's "terminated" and one to trap the "pause" condition...
Then you could do something like...
public static void main(String[] args) {
Sync hi = new Sync();
Thread t = new Thread(hi);
t.start();
Scanner d = new Scanner(System.in);
System.out.println("press enter to pause");
d.nextLine();
hi.setPaused(true);
System.out.println("press enter to resume");
d.nextLine();
hi.setPaused(false);
System.out.println("press enter to terminate");
d.nextLine();
hi.terminate();
try {
t.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Has terminated");
}
to simply run it...
You should note that it's generally discouraged to extend directly from Thread and it is generally encouraged to use a separate Runnable, there are many reasons, but one which you will find most useful in future is Runnable is more widely supported in different parts of the API (like the Executors API) making it a much more flexible option
Have a look at the Concurrency Trail for more details, in particular Lock Objects
Update : Thanks everyone! I've modified the program as per the suggestions and the code given below is the modified code.
Original Post :
I've gone through some "Apply and Analyze" type of questions and in one question, the programmer has been asked to apply multithreading concept for three reservation counters of a cinema theater and calculate the total booking numbers and amount collected in a show.
And I've written a program for the same which you can see below:
import java.io.*;
import java.lang.*;
class Cinema
{
int no=0,price=0;
synchronized void reservation(int n,int p)
{
no=no+n;
price=price+p;
}
}
class Counter implements Runnable
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Cinema c;
int not,cost;
Counter(Cinema c)
{
this.c=c;
}
public void run()
{
try
{
System.out.print("\nCounter 1");
System.out.print("\nEnter the no. of tickets :");
not=Integer.parseInt(br.readLine());
cost=not*150;
c.reservation(not,cost);
}
catch(IOException e){System.out.print("\n"+e);}
}
}
class CinemaMain
{
public static void main(String args[])throws IOException
{
Cinema c=new Cinema();
System.out.print("\nCounter 1");
Thread c1=new Thread(new Counter(c));
c1.start();
c1.join();
System.out.print("\nCounter 2");
Thread c2=new Thread(new Counter(c));
c2.start();
c2.join();
System.out.print("\nCounter 3");
Thread c3=new Thread(new Counter(c));
c3.start();
c3.join();
try
{
Thread.sleep(500);
}
catch(InterruptedException ie)
{
System.out.print("\n"+ie);
}
System.out.print("\nTotal no. of tickets :"+c.no);
System.out.print("\nTotal Money collected:"+c.price);
}
}
I can compile it just fine, but when I run the program, this is what I get -->LINK (since I don't have 10 reputation, I couldn't post the image here, sorry!) I don't know why, it doesn't ask for input even though I've written the code to get input in the run method.
I can compile it just fine, but when I run the program, this is what I get ...
There are a couple of things wrong with your program:
The main thread is not waiting for the Counter threads to finish before it prints out the totals. If you need to wait for a thread to complete then you call thread.join() on it.
Thread counter1 = new Thread(new Counter1(c));
counter1.start();
// start other threads here...
// now wait for the counter1 to finish
counter1.join();
In your case, the 3 Counters are forked but the main only sleeps a bit and then quits. The Counter threads are still running.
Each of the Counter threads is adding values to fields inside the Cinema but there is no synchronization in Cinema. Anytime two threads are modifying the same field, there must be some mutex protection and memory synchronization.
The easy thing to do here is to make the Cinema.reservation(...) method be synchronized. Then each of the Counter objects will get a lock on the Cinema instance which will ensure only one Counter updates the Cinema at one time. The synchronized keyword also ensures that the fields in the Cinema object are memory synchronized as well.
synchronized void reservation(int n,int p) { ...
As always, you should consider using the ExecutorService classes instead of forking threads yourself. See the Java tutorial.
Try this Approach ;
import java.io.*;
import java.lang.*;
public class Cinema
{
int no=0,price=0;
synchronized void reservation(int n,int p)
{
no=no+n;
price=price+p;
}
public static void main(String args[])throws IOException, InterruptedException
{
Cinema c=new Cinema();
Thread t1 = new Thread(new Counter(c,"Counter 1"));
t1.start();
Thread t2 = new Thread(new Counter(c,"Counter 2"));
t2.start();
Thread t3 = new Thread(new Counter(c,"Counter 3"));
t3.start();
t1.join();
t2.join();
t3.join();
try
{
Thread.sleep(100);
}
catch(InterruptedException ie)
{
System.out.print("\n"+ie);
}
System.out.print("\nTotal no. of tickets :"+c.no);
System.out.print("\nTotal Money collected:"+c.price);
}
}
class Counter implements Runnable
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Cinema c;
int not,cost;
String counterName;
Counter(Cinema c,String counterName)
{
this.c=c;
this.counterName=counterName;
}
public void run()
{
try
{
synchronized(c) {
System.out.print("\n" + counterName);
System.out.print("\nEnter the no. of tickets :");
not=Integer.parseInt(br.readLine());
cost=not*150;
c.reservation(not,cost);
}
}
catch(IOException e){System.out.print("\n"+e);}
}
}
I have made a single Counter class instead of 3 classes you are using.
I made the reservation method to be synchronized.
I called join method on all the three threads. So the program will not terminate abruptly.TGhe last thread that would teminate would be main.
In run() method , I locked the Cinema object c. This will resolve your issue of Buffered Reader at this moment of time. But in real world scenario different threads will be run by different people. So no need to lock the Cinema object there.it is just for your usage.
Why do you need to make threads when you can just make it way simpler?
import java.io.*;
import java.lang.*;
import java.util.Scanner;
public class Cinema {
public Cinema(){
int no=0,price=0;
}
public int Count () {
int not,not2, not3, cost,cost2,cost3;
System.out.print("\nCounter 1");
System.out.print("\nEnter the no. of tickets: ");
Scanner br=new Scanner(System.in);
String input=br.nextLine();
not=Integer.parseInt(input);
cost=not*150;
System.out.println("Cost of tickets: "+cost);
System.out.print("\nCounter 2");
System.out.print("\nEnter the no. of tickets: ");
Scanner br2=new Scanner(System.in);
String input2=br2.nextLine();
not2=Integer.parseInt(input2);
cost2=not2*150;
System.out.println("Cost of tickets: "+cost2);
System.out.print("\nCounter 3");
System.out.print("\nEnter the no. of tickets: ");
Scanner br3=new Scanner(System.in);
String input3=br3.nextLine();
not3=Integer.parseInt(input3);
cost3=not3*150;
System.out.println("Cost of tickets: "+cost3);
int total=cost+cost2+cost3;
int tickets=not+not2+not3;
System.out.println("Total price for tickets is: "+total);
System.out.println("Total number of tickets is: "+tickets);
return total;
}
public static void main(String args[])
{
Cinema c=new Cinema();
c.Count();
}
}