Constructor and method not working as expected in Java program
I have the following code:
package principal;
public class Principal {
public static void main(String[] args) {
Thread filosofos[]=new Thread[5];
for (int i=0;i<5;i++) {
System.out.println("loop");
filosofos[i]=new Thread();
filosofos[i].start();
}
// TODO Auto-generated method stub
}
}
package principal;
public class Filosofo implements Runnable{
static final int tamanho=5;
static int talheres[]=new int[tamanho];
static Semaforo semaforo= new Semaforo(1);
static int quantidade=0;
int id;
public Filosofo(){
System.out.println("Construtor iniciado.");
for (int i=0;i<tamanho;i++) {
talheres[i]=0;
}
quantidade++;
id=quantidade;
}
public void run () {
System.out.println("Filosofo "+id+" iniciado");
try {
// Filosofo pensando
Thread.sleep(1000);
} catch (Exception e) {
}
semaforo.down();
System.out.println("Filosofo "+id+" comendo");
semaforo.up();
}
}
The program should exhibit the string "Construtor iniciado." and the other 2 strings of method run. However when I run the code nothing happens only output that I receive is
loop
loop
loop
loop
loop
why the string of the constructor is not showing up? Why the method run is not running as expected? It looks like the constructor and the method run are not running at all, and I don't know what is going wrong.
You have declared class Filosofo but you never create a single instance of it.
Perhaps you want to pass a new instance of Filosofo as thread constructor parameter for each thread?
package principal;
public class Principal
{
public static void main(String[] args)
{
Thread filosofos[]=new Thread[5];
for (int i=0;i<5;i++) {
filosofos[i]=new Thread(new Filosofo());
filosofos[i].start();
}
}
}
Except this, instead of using a static field for counting Filosofo instances and assign them an id, why you don't just pass the id in the constructor?
Also the other fields, don't need to be static, pass the shared fields, like semaforo, in the constructor and copy them in a class field.
I don't know the meaning of talheres field and I don't understand why you reinitialize a static field in each instance constructor, maybe you can just initialize once in main and pass that field in the constructor of each Filosofo, as you know, arrays are not copied, only a reference to them is copied.
Also instead of catch (Exception e) you should use catch (InterruptedException e).
You should do something useful with the exception, like printing it.
If you intend to ignore an exception at least you should add a very detailed comment on why you are doing that.
You never instantiate any Filosofo, just Threads.
Related
I know there is, like, over 5 questions that ask this but mine is different. I am trying to get all classes in a package and run the tick function. Here is what one of my classes look like:
package com.stupidrepo.mydirectory.yayay;
public class test {
public void tick(MinecraftClient client) {
System.out.println(client.player.getName());
}
}
Here is how I am attempting to call this function:
ScanResult scanResult = new ClassGraph().acceptPackages("com.stupidrepo.mydirectory.yayay").enableClassInfo().scan();
private void doIt(MinecraftClient client) {
scanResult.getAllClasses().forEach((classInfo -> {
// System.out.println(classInfo.getName());
try {
classInfo.loadClass().getMethod("tick", MinecraftClient.class).invoke(null, client);
} catch (Exception e) {
e.printStackTrace();
}
}));
}
When I call the doIt function, it keeps giving me the java.lang.NoSuchMethodException error. When I print classInfo.getMethods();, it shows me [public void com.stupidrepo.mydirectory.yayay.test.tick(net.minecraft.client.MinecraftClient)].
So the method is there but java says it isn't. Please help! (By the way the code is for a Fabric MC mod)
The method tick is not static. But, when you are invoking method, you are not giving instance (but null), so it try to run the method as static. Such as It's not static, it failed.
To fix it, you can:
Set your method as static, for example:
package com.stupidrepo.mydirectory.yayay;
public class test {
public static void tick(MinecraftClient client) {
System.out.println(client.player.getName());
}
}
Create a new instance like that:
try {
Class<?> clzz = classInfo.loadClass(); // get class
Object obj = clzz.getConstructor().newInstance(); // create instance
clzz.getMethod("tick", MinecraftClient.class).invoke(obj, client); // get and call method
} catch (Exception e) {
e.printStackTrace();
}
I have a utility class which starts a long running background thread. The utility class is initialized in main class. But utility class object is getting garbage collected. How can i prevent that. Here is my class structure.
public class Main {
public static void main(String[] args) throws Exception {
Utility u = new Utility();
u.startTask(); //This is not referenced after this and hence getting gc'ed
.....
....
api.addMessageCreateListener(event -> {
/////continuously running
}
}
}
What i want is to prevent Utility object from getting garbage collected.
I assume the Method Utility#startTask() starts Threads on its own, otherwise this would be a blocking call and the main-Method would not end before startTask returned.
However this should not stop you from implementing the Runnable Interface in Utility itself. As long as the Utility runs in its own Thread, you do not need to worry about the enclosing method returning. Since the Tread is still running, the Instance will not be collected.
public class Threading {
public static void main(String[] args) {
Utility utility = new Threading().new Utility();
Future utilFuture = Executors.newSingleThreadExecutor().submit(utility);
System.out.println("end main");
}
public class Utility implements Runnable {
#Override
public void run() {
System.out.println("Start Utility");
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println("foo: " + i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
}
}
}
}
}
Note: In your case you might not need the Future, but it is an extremely useful tool to interrupt the Execution if needed.
Okay so I have a bit a conundrum. I have a Qaurtz Cron that I want to use to schedule and run some Java Tests. These task are scheduled through a gui that Uses JavaFX. However, the job itself calls a run tests method. The job forces me to make certain elements static, but by making them static, I get a null pointer exception. I would really appreciate some help here.
So here is the job class that forces things to be static.
public class newJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("We are attempting the job now");
try {
FXMLDocumentController.runScheduledTests();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Inside my controller I have something like this:
public static void runTests() throws SQLException, IOException {
// Set running to true. In current form we do not use this bool,
// however, we may
// make changes that rely on this.
running = true;
FileOutputStream fos = null;
// Verify that users exist, and there is a url with the word max in it
int count = DBHelpers.getResults("SELECT * FROM USERS;", new String[] { "ID" }).length();
// Verify that we have both users and a maximo url to work with.
if ((!userList.isEmpty() || count > 0) && userMaxListChoice.length() > 5) {
// Set the proper driver, default to chrome if none is selected
if (IEbutton.isSelected()) {
BrowserConfig.setDriver(Browsers.IE());
} else {
BrowserConfig.setDriver(Browsers.Chrome());
}
// Let's assign maximo. If no one has clicked the use UserList
// button, assume that the data inside
// maximo name is good to use
if (userMaxListChoice != null) {
BrowserConfig.setMaximo(userMaxListChoice);
// System.out.println("used maxLIst choice");
} else {
// If the user has not selected a name from the maximo list,
// let's grab whatever
// they have entered in the maximoName field.
BrowserConfig.setMaximo(maximoName.getText());
}
// Set the system pause based on the interval string
int pause = Integer.parseInt(interval.getText().toString());
// Make sure the puase is in miliseconds
pause = pause * 1000;
BrowserConfig.setInterval(pause);
Note that the runScheduledTests() methods does some configuring and calls the runTest method. Inside the run test method is where I'm hitting the error specifically this line:
if (IEbutton.isSelected()) {
BrowserConfig.setDriver(Browsers.IE());
} else {
BrowserConfig.setDriver(Browsers.Chrome());
}
The reason is that above I have this :
#FXML
public static RadioButton ChromeButton;
#FXML
public static RadioButton IEbutton;
As I said this is a bit of an issue, If I don't make them static the job class yells at me for making a non-static reference.
How can I resolve this conflict?
TL;DR : You shouldn't use static on the fields annotated with #FXML.
For more information go through - javafx 8 compatibility issues - FXML static fields
You could load the FXML by using the FXMLLoader and then get an instance of the controller from it. By doing this, you can convert the method runScheduledTests() into a non-static method.
public class newJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
try {
FXMLLoader fxmlLoader =
new FXMLLoader(getClass().getResource("path-to-fxml.fxml"));
fxmlLoader.load();
FXMLDocumentController fxmlDocumentController =
(FXMLDocumentController)fxmlLoader.getController();
fxmlDocumentController.runScheduledTests(); // convert the method to non-static
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The problem is you are trying to use static when the controller itself is not static. Take into consideration I recommend taking a look at the difference between static and non-static here. In regards to fixing your code. First make your buttons ChromeButton and IEbutton not static. Then when your application class, something like this:
public class HelloWorld extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
//pass a reference of your stage to job.
}
}
Then Pass a reference of your buttons or controller into the Job class as a variable. Like this:
public class newJob implements Job{
private RadioButton chrome;
private RadioButton ie;
public newJob(RadioButton chrome, RadioButton ie) {
this.chrome = chrome;
this.ie = ie;
}
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("We are attempting the job now");
try {
FXMLDocumentController.runScheduledTests();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The core of your problem is controller variables CANNOT be static as the controller is dependent on instantiating the class and passing the required information in. The best way to fix this is by passing a reference either to the buttons or the class by using variables in the constructor. Please read the link I sent you to get a better understanding between static and non-static. Also, if you are confused about constructors take a look here as well.
Can someone help me to understand why java is trying to make an instance of a before b. And also, why it is looping between line 2 and line 3?
public class Winterfell {
private Winterfell a= new Winterfell();
public Winterfell() throws Exception {
throw new Exception("Fire and Ice");
}
public static void main(String[] args) {
try {
Winterfell b = new Winterfell();
System.out.println("Surprise!");
} catch (Exception ex) {
System.out.println("I told you so");
}
}
}
This will cause a StackOverflowError.
By having a field referencing a new object of the same class or by making a new object of the same class in the constructor you have an infinite number of calls to create a new Winterfell object.
That is why it is looping.
To fix this you likely want to remove private Winterfell a= new Winterfell(); so that a single Winterfell object is created.
private Winterfell a= new Winterfell();
Is invoked prior to invoking the constructor of Winterfell because it's a data member. Check out the Oracle documentation for object construction for more info.
I have a static function like:
public static void foo()
{
//code follows
System.out.println(Thread.currentThread().getName());
//code follows
}
and multiple threads are calling this function concurrently. I have set the names of threads using
Thread.setName(String)
When i execute the code, the print statement will print the name of only one thread. How can i identify the names of all the threads currently executing the foo() function?
EDIT:
public class FooThread extends Thread
{
public FooThread(String name)
{
this.setName(name);
}
#Override public void run()
{
//do something
//do something
Main.foo();
}
}
//Main Class
public class Main
{
public static void main(String[] args)
{
for(int i=0;i<6;++i)
{
new FooThread("Thread"+i).start();
}
}
public static void foo()
{
//do something
while(true)
{
//do something
System.out.println(Thread.currentThread().getName());
}
}
}
You're already showing the name of the Thread that is calling your code. Code that proves this:
public class Foo2 {
public static synchronized void foo() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
int maxCount = 10;
for (int i = 0; i < maxCount; i++) {
Thread thread = new Thread(new Runnable() {
public void run() {
foo();
}
});
thread.setName("Thread " + i);
thread.start();
long sleepTime = 1000;;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
}
}
Return:
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Thread 5
Thread 6
Thread 7
Thread 8
Thread 9
Your problem lies in code not shown.
Either your method is being called by one and only one thread, or
Or you're giving all your threads the same name.
Again, for a complete solution as to what is actually wrong with your current set up, create and post an sscce similar to what I've posted above. For all we know you could be calling run() on your Threads, and until we can see and reproduce your problem, I don't think that we'll be able to fully understand it.
EDIT
Regarding your SSCCE: Compare the results of the two methods below, foo1() and foo2()
class FooThread extends Thread {
public FooThread(String name) {
this.setName(name);
}
#Override
public void run() {
// do something
// do something
Main.foo1(); // !! Swap comments
// Main.foo2(); // !! Swap comments
}
}
// Main Class
public class Main {
private static final long SLEEP_TIME = 4;
public static void main(String[] args) {
for (int i = 0; i < 6; ++i) {
new FooThread("Thread" + i).start();
}
}
public static void foo1() {
// do something
while (true) {
// do something
synchronized (Main.class) {
System.out.println(Thread.currentThread().getName());
}
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
}
public static void foo2() {
while (true) {
System.out.println(Thread.currentThread().getName());
}
}
}
If your while loop isn't so tight, but yields the CPU with say a short Thread.sleep, you'll see more of the different threads sharing foo in closer proximity.
But again, your code also proves that your Thread names *are8 being displayed, but that you're only seeing one name likely because that thread is hogging the CPU.
Another option is to get all the Thread stacks and look for all the threads in the foo() This has the benefit of no overhead or extra code, except to capture the information you want.
BTW: Can you make it clearer why do you need this information as I suspect there is a better way to do what you really want?
If you only want to get the count of threads, use a thread-safe counter to store number of threads. Increase the counter when foo() begins, and decrease the counter when foo() exits.
If you need to get the names, use a hash set (or list if there are duplicates of thread names) to store the names: Add the name when foo() begins, and remove the name when foo() exits. Make sure the access to hash set is thread safe. You also need another method to print out the content of the hash set, so you can call it any time to see what are the name of threads executing foo().
You can put the name into a list when the method starts (in a synchronized block) and remove it at the end again.
List allTheNames = Collections.synchronizedList(new ArrayList<String>());
public void foo() {
allTheNames.add(Thread.currentThread().getName());
// now allTheNames contains all the names of all threads currently in this method.
System.out.println(allTheNames.toString());
allTheNames.remove(Thread.currentThread().getName());
}
Of course, if you change the name of the thread in the meantime that wont work, but why would you do so?
You could also store the Thread itself if you need other informations that the name.