1

I'm fairly new to Java and I cannot for the life of me find out how to do this.

public class Main {

    public static void main(String[] args) {
        Test test1 = new Test(2);
        Test test2 = new Test(3);
    }
}

class Test {
    int i;

    public Test(int i) {
        this.i = i;
    }
    // Constantly print out i
}

Basically, just for this, I'm trying to make the class constantly output its own variable of i. I know there's a way to do this by making a getter method and putting the objects in an ArrayList, but I'm making a Minecraft plugin that requires this specific case. Thank you!

  • 1
    This what for java threads are! – kofemann Apr 25 '20 at 16:36
  • 1
    I recommend the [Concurrency](https://docs.oracle.com/javase/tutorial/essential/concurrency/) lesson in the _Essential Classes_ trail which is part of Oracle's java tutorials. – Abra Apr 25 '20 at 16:51

2 Answers2

2

Executors framework

As said in the Answer by kofemann, use threads to run code in the background. But handling threads directly is tricky business. So the Executors framework was added to Java to make this work easier.

In particular, you want a ScheduledExecutorService to perform some task over and over. Use the Executors class to get an instance of a ScheduledExecutorService, backed by a pool of one or more threads. Give that task a Runnable object whose run method performs your desired task. Specify an initial delay, or zero to start immediately. And specify a period, an amount of time to pass before performing the task again.

Important: Be sure to eventually shutdown your executor service, when you no longer need it, or when your app is quitting. Otherwise the threads may continue running indefinitely.

Here is a Count class to hold our count integer.

package work.basil.example;

public class Count
{
    private int count;

    public Count ( int count )
    {
        this.count = count;
    }

    public int getCount ( ) { return this.count; }
}

And here is some example code. We define a runnable, configure an executor service, start it running, wait a while, then shutdown the executor service.

Count count = new Count( 42 );

Runnable runnable = ( ) -> {
    int i = count.getCount();
    System.out.println( "Count is currently: " + i + " at " + ZonedDateTime.now() );
};

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
long delay = 0;
long period = 5;
ses.scheduleAtFixedRate( runnable , delay , period , TimeUnit.SECONDS );

// … eventually shutdown your executor service and its backing thread pool.
try
{
    Thread.sleep( TimeUnit.MINUTES.toMillis( 1 ) );
}
catch ( InterruptedException e )
{
    e.printStackTrace();
}
ses.shutdown();
System.out.println( "Done running example of scheduled executor service." );

When run.

Count is currently: 42 at 2020-04-25T13:08:14.484127-07:00[America/Los_Angeles]

Count is currently: 42 at 2020-04-25T13:08:19.465306-07:00[America/Los_Angeles]

Count is currently: 42 at 2020-04-25T13:09:14.460006-07:00[America/Los_Angeles]

Done running example of scheduled executor service.

Sharing resources across threads, in this case the Count instance and its contained int variable, carries complications. Study the superb book Java Concurrency in Practice by Brian Goetz, et al.

I imagine that you intend to increment that count during the execution of your app. If so, we must protect access to the count because one thread could be modifying the number while another is reading it.

Java provides the AtomicInteger class for this purpose. Change the primitive int in our Count class to use AtomicInteger object instead. We add an increment method to increase the value of that AtomicInteger. And we use the thread-safe AtomicInteger::get method to retrieve its value.

package work.basil.example;

import java.util.concurrent.atomic.AtomicInteger;

public class Count
{
    private AtomicInteger count;

    public Count ( int count )
    {
        this.count = new AtomicInteger( count );
    }

    public int getCount ( ) { return this.count.get(); }

    public int increment ( ) { return this.count.incrementAndGet(); }
}

We need not make any changes to our code that uses Count class.

If you want to see the incrementing in action, set up another Runnable task. Schedule that task on the executor service as well as our other Runnable.

Count count = new Count( 42 );

Runnable runnable = ( ) -> {
    int i = count.getCount();
    System.out.println( "Count is currently: " + i + " at " + ZonedDateTime.now() );
};

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
long delay = 0;
long period = 5;
ses.scheduleAtFixedRate( runnable , delay , period , TimeUnit.SECONDS );

Runnable runnableIncrementor = ( ) -> {
    int i = count.increment();
    System.out.println( "Incrementing count: " + i + " at " + ZonedDateTime.now() );
};
ses.scheduleAtFixedRate( runnableIncrementor , 7 , 13 , TimeUnit.SECONDS );

// … eventually shutdown your executor service and its backing thread pool.
try
{
    Thread.sleep( TimeUnit.MINUTES.toMillis( 1 ) );
}
catch ( InterruptedException e )
{
    e.printStackTrace();
}
ses.shutdown();
System.out.println( "Done running example of scheduled executor service." );

When run.

Count is currently: 42 at 2020-04-25T13:26:14.405538-07:00[America/Los_Angeles]

Count is currently: 42 at 2020-04-25T13:26:19.372358-07:00[America/Los_Angeles]

Incrementing count: 43 at 2020-04-25T13:26:21.379639-07:00[America/Los_Angeles]

Count is currently: 43 at 2020-04-25T13:26:24.371442-07:00[America/Los_Angeles]

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

This is for for java threads are. Here is an example.

public class Main {

    public static void main(String[] args) {
        new Test(2).start();
        new Test(3).start();

        // some code to wait for thread completion 
    }
}

class Test extends Thread {
    int i;

    public Test(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        while(true) {
            // Constantly print out i
        }
    }
}

Well, there is much better ways to do it, but you got the idea.

kofemann
  • 4,217
  • 1
  • 34
  • 39
  • 1
    `extends Thread` -> [“implements Runnable” vs “extends Thread” in Java](https://stackoverflow.com/q/541487) – Pshemo Apr 25 '20 at 16:47
  • 1
    Even better: Use the [*Executors*](https://docs.oracle.com/javase/tutorial/essential/TOC.html) framework rather than manage the threads directly. – Basil Bourque Apr 25 '20 at 19:10
  • Sure. As mentioned in the answer, this is just a direction, not the solution. – kofemann Apr 25 '20 at 22:06