Oi Felipe, tudo bem? 
Uma forma de você notificar a activity seria por meio do designer pattern Delegate. 
Considerando o contexto no qual você mencionou, basicamente você faria com que a sua activity implementasse uma interface que representasse o comportamento que você espera, por exemplo a seguinte interface:
public interface AtualizadorDeLista {
    public void atualiza(List<Aluno> alunos);
}
Então a activity ficaria assim:
public class ListaAlunoActivity extends AppCompatActivity implements AtualizadorDeLista {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    //código
        new ReceberDadosTask(this).execute();
    }
    @Override
    public void atualiza(List<Aluno> alunos) {
        //código que atualiza lista
    }
}
Na sua AsyncTask, basicamente você receberia a interface na qual você implementou na Activity, pois dessa forma, você garante que qualquer um que usar essa async task vai ter o método que atualiza lista:
class ReceberDadosTask extends AsyncTask {
    private AtualizadorDeLista atualizadorDeLista;
    public ReceberDadosTask(AtualizadorDeLista atualizadorDeLista) {
        this.atualizadorDeLista = atualizadorDeLista;
    }
    @Override
    protected List<Aluno> doInBackground(Object[] params) {
    List<Aluno> alunos = getAlunos();
        return alunos;
    }
    @Override
    protected void onPreExecute(List<Aluno> alunos) {
        super.onPreExecute();
        atualizadorDeLista.atualiza(alunos);
    }
}
Essa é uma das técnicas que usamos para poder realizar essa comunicação. Sim, ela desacopla um pouco, porém ainda sim mantém o acoplamento com a interface... 
Uma outra maneira é o uso por meio do eventbus que é uma biblioteca que permite enviar mensagens entre entidades do Android. No curso de sincronização de Android e Web Service é ensinada duas bibliotecas que facilita a vida do desenvolvedor para realizar o que você pretende fazer.
Espero ter ajudado.
Abraços.