diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index dcc7838..db184c0 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,7 @@
 linkchecker 7.x-dev, nightly
 ----------------------------
 
+* #380052: Add support with non-blocking parallel link checking.
 * #1867460: Prevent save on automatic updates, if content has not changed.
 * #1804842 follow up: Exit if all node types are disabled
 * #1450672: Cron task does not impersonate to admin user on automatic content updates.
diff --git a/linkchecker.admin.inc b/linkchecker.admin.inc
index 5f3907d..b11e54e 100644
--- a/linkchecker.admin.inc
+++ b/linkchecker.admin.inc
@@ -124,11 +124,31 @@ function linkchecker_admin_settings_form($form_state) {
     '#description' => t('If a filter has been enabled for an input format it runs first and afterwards the link extraction. This helps the link checker module to find all links normally created by custom filters (e.g. Markdown filter, Bbcode). All filters used as an inline references (e.g. Weblink filter <code>[link: id]</code>) to other content and filters only wasting processing time (e.g. Line break converter) should be disabled. This setting does not have any effect on how content is shown on a page. This feature optimizes the internal link extraction process for link checker and prevents false alarms about broken links in content not having the real data of a link.'),
   );
 
+  $count_lids_enabled = db_query("SELECT count(lid) FROM {linkchecker_link} WHERE status = :status", array(':status' => 1))->fetchField();
+  $count_lids_disabled = db_query("SELECT count(lid) FROM {linkchecker_link} WHERE status = :status", array(':status' => 0))->fetchField();
   $form['check'] = array(
     '#type' => 'fieldset',
     '#title' => t('Check settings'),
+    '#description' => t('For simultaneous link checks it is recommended to install the <a href="@httprl">HTTP Parallel Request Library</a>. This may be <strong>necessary</strong> on larger sites with very many links (30.000+), but will also improve overall link check duration on smaller sites. Currently the site has @count links (@count_enabled enabled / @count_disabled disabled).', array('@httprl' => 'http://drupal.org/project/httprl', '@count' => $count_lids_enabled+$count_lids_disabled, '@count_enabled' => $count_lids_enabled, '@count_disabled' => $count_lids_disabled)),
     '#collapsible' => FALSE,
   );
+  $form['check']['linkchecker_check_library'] = array(
+    '#type' => 'select',
+    '#title' => t('Check library'),
+    '#description' => t('Defines the library that is used for checking links.'),
+    '#default_value' => variable_get('linkchecker_check_library', 'core'),
+    '#options' => array(
+      'core' => t('Drupal core'),
+      'httprl' => t('HTTP Parallel Request Library'),
+    ),
+  );
+  $form['check']['linkchecker_check_connections_max'] = array(
+    '#type' => 'select',
+    '#title' => t('Number of simultaneous connections'),
+    '#description' => t('Defines the maximum number of simultaneous connections that can be opened by the server. HTTP Parallel Request Library make sure that a single domain is not overloaded beyond RFC limits. For small hosting plans with very limited CPU and RAM it may be required to reduce the default limit.'),
+    '#default_value' => variable_get('linkchecker_check_connections_max', 8),
+    '#options' => drupal_map_assoc(array(2, 4, 8, 16, 32, 64, 128)),
+  );
   $form['check']['linkchecker_check_useragent'] = array(
     '#type' => 'select',
     '#title' => t('User-Agent'),
diff --git a/linkchecker.drush.inc b/linkchecker.drush.inc
index f095bba..11daccc 100644
--- a/linkchecker.drush.inc
+++ b/linkchecker.drush.inc
@@ -86,6 +86,6 @@ function drush_linkchecker_clear() {
  */
 function drush_linkchecker_check() {
   drush_log('Starting link checking...', 'status');
-  linkchecker_cron();
+  _linkchecker_check_links();
   drush_log('Finished checking links.', 'status');
 }
diff --git a/linkchecker.install b/linkchecker.install
index 45e458a..402c56a 100644
--- a/linkchecker.install
+++ b/linkchecker.install
@@ -19,6 +19,8 @@ function linkchecker_install() {
 function linkchecker_uninstall() {
   variable_del('linkchecker_action_status_code_301');
   variable_del('linkchecker_action_status_code_404');
+  variable_get('linkchecker_check_connections_max');
+  variable_del('linkchecker_check_library');
   variable_del('linkchecker_check_links_interval');
   variable_del('linkchecker_check_links_types');
   variable_del('linkchecker_check_useragent');
diff --git a/linkchecker.module b/linkchecker.module
index bd5a6da..91faff8 100644
--- a/linkchecker.module
+++ b/linkchecker.module
@@ -386,31 +386,63 @@ function _linkchecker_link_block_ids($link) {
  * Implements hook_cron().
  */
 function linkchecker_cron() {
-  // Get max_execution_time from configuration, override 0 with 240 seconds.
-  $max_execution_time = ini_get('max_execution_time') == 0 ? 240 : ini_get('max_execution_time');
-
   // Remove outdated links no longer in use once per day.
   if (REQUEST_TIME - variable_get('linkchecker_cleanup_links_last', 0) >= 86400) {
     _linkchecker_cleanup_links();
     variable_set('linkchecker_cleanup_links_last', REQUEST_TIME);
   }
 
+  // Run the link checks.
+  _linkchecker_check_links();
+}
+
+/**
+ * Run link checks.
+ *
+ * @param bool $background
+ *   Defines if a background process should be used to run the link checks.
+ */
+function _linkchecker_check_links($background = FALSE) {
+  $linkchecker_check_library = variable_get('linkchecker_check_library', 'core');
+  $has_httprl = (module_exists('httprl') && $linkchecker_check_library == 'httprl');
+
+  if ($has_httprl && !$background) {
+    // Setup callback options array; call linkchecker_cron(TRUE) in the background.
+    $callback_options = array(
+      array(
+        'function' => '_linkchecker_check_links',
+      ),
+      TRUE
+    );
+    // Queue up the request.
+    httprl_queue_background_callback($callback_options);
+
+    // Execute request.
+    httprl_send_request();
+    return;
+  }
+
+  // Get max_execution_time from configuration, override 0 with 240 seconds.
+  $max_execution_time = ini_get('max_execution_time') == 0 ? 240 : ini_get('max_execution_time');
+  // Make sure we have enough time to validate all of the links.
+  drupal_set_time_limit(240);
+
   // Do not confuse admins with a setting of maximum checkable links per cron
   // run and guess that 2 links can be checked per second with 1 thread, what is
   // nevertheless uncommon. The max_execution_time can be used to calculate
   // a useful value that is higher, but not totally out of scope and limits the
   // query resultset to a resonable size.
-  $check_links_max_per_cron_run = $max_execution_time;
+  $linkchecker_check_connections_max = variable_get('linkchecker_check_connections_max', 8);
+  $check_links_max_per_cron_run = ($has_httprl) ? ($linkchecker_check_connections_max * $max_execution_time) : $max_execution_time;
 
   $linkchecker_check_links_interval = variable_get('linkchecker_check_links_interval', 2419200);
   $linkchecker_check_useragent = variable_get('linkchecker_check_useragent', 'Drupal (+http://drupal.org/)');
 
   // Get URLs for checking.
   $links = db_query_range('SELECT * FROM {linkchecker_link} WHERE last_checked < :last_checked AND status = :status ORDER BY last_checked, lid ASC', 0, $check_links_max_per_cron_run, array(':last_checked' => REQUEST_TIME - $linkchecker_check_links_interval, ':status' => 1));
-  foreach ($links as $link) {
-    // Make sure we have enough time to validate the link.
-    drupal_set_time_limit(240);
+  $links_remaining = $links->rowCount();
 
+  foreach ($links as $link) {
     $headers = array();
     $headers['User-Agent'] = $linkchecker_check_useragent;
 
@@ -418,12 +450,42 @@ function linkchecker_cron() {
     // required to prevent timeouts on URLs that are large downloads.
     if ($link->method == 'GET') { $headers['Range'] = 'bytes=0-1024'; }
 
-    // Fetch URL.
-    $response = drupal_http_request($link->url, array('headers' => $headers, 'method' => $link->method, 'max_redirects' => 0));
-    _linkchecker_status_handling($link, $response);
+    // Add in the headers.
+    $options = array(
+      'headers' => $headers,
+      'method' => $link->method,
+      'max_redirects' => 0,
+    );
+
+    if ($has_httprl) {
+      // Define the callback and add the $link object to it.
+      $options += array(
+        'global_connections' => $linkchecker_check_connections_max,
+        'global_timeout' => 180 - (timer_read('page') / 1000),
+        'callback' => array(
+          array(
+            'function' => '_linkchecker_status_handling',
+          ),
+          $link, // This need to be passed or it's not send back to _linkchecker_status_handling()
+        )
+      );
+
+      // Queue up the requests.
+      httprl_request($link->url, $options);
+      $links_remaining--;
 
-    if ((timer_read('page') / 1000) > ($max_execution_time / 2)) {
-      break; // Stop once we have used over half of the maximum execution time.
+      // After all links are queued, run the url checks.
+      if ($links_remaining == 0) {
+        httprl_send_request();
+      }
+    }
+    else {
+      $response = drupal_http_request($link->url, $options);
+      _linkchecker_status_handling($response, $link);
+
+      if ((timer_read('page') / 1000) > ($max_execution_time / 2)) {
+        break; // Stop once we have used over half of the maximum execution time.
+      }
     }
   }
 }
@@ -431,13 +493,13 @@ function linkchecker_cron() {
 /**
  * Status code handling.
  *
- * @param string $link
- *   An object containing the url, lid and fail_count.
  * @param object $response
  *   An object containing the HTTP request headers, response code, headers,
  *   data and redirect status.
+ * @param string $link
+ *   An object containing the url, lid and fail_count.
  */
-function _linkchecker_status_handling($link, $response) {
+function _linkchecker_status_handling(&$response, $link) {
   $ignore_response_codes = preg_split('/(\r\n?|\n)/', variable_get('linkchecker_ignore_response_codes', "200\n206\n302\n304\n401\n403"));
 
   // - Prevent E_ALL warnings in DB updates for non-existing $response->error.
@@ -456,6 +518,7 @@ function _linkchecker_status_handling($link, $response) {
   }
 
   switch ($response->code) {
+    case  -2: // HTTPRL: maximum allowed redirects exhausted.
     case 301:
       // Remote site send status code 301 and link needs an update.
       db_update('linkchecker_link')
@@ -666,6 +729,9 @@ function _linkchecker_status_handling($link, $response) {
         // watchdog('linkchecker', 'Unhandled link error %link has been found.', array('%link' => $link->url), WATCHDOG_ERROR, l(t('Broken links'), 'admin/reports/linkchecker'));
       }
   }
+  // Free Memory.
+  $response = new StdClass();
+  unset($response);
 }
 
 /**
