def METHOD_NAME(self, songs: List[Song]) -> List[Optional[str]]:
    """
    Get the download urls for a list of songs.
    ### Arguments
    - songs: List of Song objects
    ### Returns
    - A list of urls if successful.
    ### Notes
    - This function is multi-threaded.
    """
    urls: List[Optional[str]] = []
    with concurrent.futures.ThreadPoolExecutor(
        max_workers=self.downloader.settings["threads"]
    ) as executor:
        future_to_song = {
            executor.submit(self.downloader.search, song): song for song in songs
        }
        for future in concurrent.futures.as_completed(future_to_song):
            song = future_to_song[future]
            try:
                data = future.result()
                urls.append(data)
            except Exception as exc:
                logger.error("%s generated an exception: %s", song, exc)
    return urls