You can use any of the three, but I would recommend the AsyncTask and I'll explain why:
First I will tell you that in Android, the main thread is the one that handles the user interface, and the system prevents us from performing actions that require network (requests to server and those things) from the main thread, that is why it is you must use Runnable, Thread or AsyncTask.
I think maybe what works best for you is a SyncAdapter or something that performs requests periodically, using alarms and Services.
From a Service it is not necessary to use Asynctask or Runnables to make requests.
About SyncAdapters I can not help you very much, I know they exist, but I have barely touched them and they are somewhat more difficult to configure and sometimes they can be blocked.
If you use Runnable or Thread, when you would like to modify something on the screen at the end of each request or something like that, you would have to call the activity that is running and call the method "runOnUiThread" (for example, myActivity.runOnUIThread ( You pass the runnable or Thread object to run on the main thread).
But if you use AsyncTask, you avoid that runOnUiThread.
I'll give you an example:
I want to make request A to the server
I think AsyncTask
I show a loading dialog
I execute it
The asynctask makes the request and gets a result.
The asynctask ends and you can update the user interface and launch a new asyncTask (you can put a thread sleep at the beginning of each asynctask)
I explain how the AsyncTask goes:
in the onPreExecute method: you have access to the user interface, it is usually used to show dialogs to indicate that something is being loaded
in the doOnBackground method: This method is actually running on another thread, so that's where the requests are placed
in the onPostExecute method: you have access to the user interface and as a parameter it receives what the "doOnBackground" method returns as a result.
in the onProgressUpdate method: you also have access to the user interface and it is usually used when you want to notify the user of the download process or similar cases. It is called from the doOnBackground by calling the publishProgress method.
I repeat that any class is worth you, but I personally like it more in asynctask because it has different methods to access the user interface.