improved with multi-threading