multithreading in java

2019-09-22 08:26发布

问题:

I want "runnable" to run at 5tps. This is not executing paralelly.

package tt;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class mySpawner {

public int tillDone = 0;
public int tillMax = 0;
public ArrayList arrayList;
private myWorker myworking;
private ScheduledExecutorService service = Executors.newScheduledThreadPool(50);

Runnable runnable = new Runnable() {

    @Override
    public void run() {
        try {
            System.out.println(System.nanoTime());
            Thread.sleep(7000);
        } catch (InterruptedException ex) {
            Logger.getLogger(mySpawner.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
};


public void activate() {
    try {
        service = Executors.newScheduledThreadPool(50);
        service.scheduleAtFixedRate(runnable, 0, 200, TimeUnit.MILLISECONDS);
    } catch (Exception e) {//Catch exception if any
        System.err.println("Error: " + e.getMessage());
    }

}

public void deactivate() {
    service.shutdown();
}

}

回答1:

Update: Howard is right, my first example was wrong.

I verified this works if you change your active() method:

service = Executors.newScheduledThreadPool(50);
new Thread() {
    public void run() {
        long nextTime = System.currentTimeMillis();
        while (true) {
            service.submit(runnable);
            long waitTime = nextTime - System.currentTimeMillis();
            Thread.sleep(Math.max(0, waitTime));
            nextTime += 200;
        }
    }
}.start();


回答2:

Consider this:

  • Your tasks are sleeping for 7 seconds during their execution
  • You are scheduling a new task every 200ms
  • You only have 50 threads in your executor

It should be clear, I hope, that you'll run out of pooled threads in just a few seconds, and you'll lose your parallelism. You need to balance this better, either by reducing the rate or reducing the sleep. Increasing the pool size won't help, you'll still run out of threads.



回答3:

scheduleAtFixedRate does only spawn a single thread but executes the runnable provided with a fixed rate.

  • The action runs in less amount of time than the given period: in this case it is respawned with exactly the specified period.
  • The action runs longer (your case): the action is started again immediately.

If you want to have the desired behaviour you may use the following pattern: Just execute the runnable once:

service.schedule(runnable, 0, TimeUnit.MILLISECONDS);

but inside the runnable's run method add the next invokation by

service.schedule(runnable, 200, TimeUnit.MILLISECONDS);

Nevertheless consider the arithmetic as described in the answer by skaffman.