Le thread principal et les éventuels nouveaux threads interagissent entre eux d'une certaine façon.

Le thread principal constitue l'assise des threads utilisateurs et plus particulièrement des threads démons.

Dans le cas d'emploi de threads utilisateur, ceux-ci prolongent le déroulement du thread principal. Ainsi, tant que tous les threads utilisateur ne sont pas terminés, le thread principal continue à exister.

public class RelationThreads extends Thread {
    public RelationThreads() {
      super();
    }
    public void run() {
        for ( int i = 0; i < 20; i++ ) {
            afficher(i + " - Exécution du Thread");
            try {
                Thread.sleep(10);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void afficher(String msg) {
        Thread t = Thread.currentThread();
        System.out.println(msg + " : " + t.getName());
        try {
            Thread.sleep(10);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        RelationThreads t = new RelationThreads();
        t.setName("Thread utilisateur");
        t.start();

        for ( int i = 0; i < 10; i++ ) {
            t.afficher(i + " - Programme principal");
        }
    }
}

/* Affiche : 
Début du thread principal
0 - Programme principal : main
0 - Exécution du Thread : Thread utilisateur
1 - Exécution du Thread : Thread utilisateur
1 - Programme principal : main
2 - Exécution du Thread : Thread utilisateur
2 - Programme principal : main
3 - Exécution du Thread : Thread utilisateur
3 - Programme principal : main
4 - Programme principal : main
4 - Exécution du Thread : Thread utilisateur
5 - Programme principal : main
5 - Exécution du Thread : Thread utilisateur
6 - Programme principal : main
6 - Exécution du Thread : Thread utilisateur
7 - Exécution du Thread : Thread utilisateur
7 - Programme principal : main
8 - Exécution du Thread : Thread utilisateur
8 - Programme principal : main
9 - Exécution du Thread : Thread utilisateur
9 - Programme principal : main
10 - Exécution du Thread : Thread utilisateur
Fin du thread principal
11 - Exécution du Thread : Thread utilisateur
12 - Exécution du Thread : Thread utilisateur
13 - Exécution du Thread : Thread utilisateur
14 - Exécution du Thread : Thread utilisateur
15 - Exécution du Thread : Thread utilisateur
16 - Exécution du Thread : Thread utilisateur
17 - Exécution du Thread : Thread utilisateur
18 - Exécution du Thread : Thread utilisateur
19 - Exécution du Thread : Thread utilisateur*/

Le thread principal influe directement sur le déroulement d'un thread démon, puisque lorsque le thread principal s'arrête, le thread démon termine immédiatement son exécution.

public class RelationThreads extends Thread {
    public RelationThreads() {
      super();
    }
    public void run() {
        for ( int i = 0; i < 100; i++ ) {
            afficher(i + " - Exécution du Thread");
        }
    }
    public void afficher(String msg) {
        Thread t = Thread.currentThread();
        System.out.println(msg + " : " + t.getName());
        try {
            Thread.sleep(10);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        System.out.println("Début du thread principal");
        RelationThreads t = new RelationThreads();
        t.setDaemon(true);
        t.setName("Thread démon");
        t.start();

        for ( int i = 0; i < 10; i++ ) {
            t.afficher(i + " - Programme principal");
        }
        System.out.println("Fin du thread principal");
    }
}

/* Affiche : 
Début du thread principal
0 - Programme principal : main
0 - Exécution du Thread : Thread démon
1 - Exécution du Thread : Thread démon
1 - Programme principal : main
2 - Exécution du Thread : Thread démon
2 - Programme principal : main
3 - Programme principal : main
3 - Exécution du Thread : Thread démon
4 - Exécution du Thread : Thread démon
4 - Programme principal : main
5 - Exécution du Thread : Thread démon
5 - Programme principal : main
6 - Exécution du Thread : Thread démon
6 - Programme principal : main
7 - Exécution du Thread : Thread démon
7 - Programme principal : main
8 - Exécution du Thread : Thread démon
8 - Programme principal : main
9 - Exécution du Thread : Thread démon
9 - Programme principal : main
10 - Exécution du Thread : Thread démon
Fin du thread principal
11 - Exécution du Thread : Thread démon
12 - Exécution du Thread : Thread démon
*/

Plusieurs threads sont démarrés automatiquement par la machine virtuelle Java et fonctionnent indépendamment des threads créés par l'utilisateur. Ces threads permettent d'accomplir des tâches précises, telles que l'activation du collecteur de déchêts (Finalizer), la gestion de composants graphiques (AWT-Windows), la gestion événementielle (AWT-EventQueue-0), etc..

public class Interruption extends Thread {
  public Interruption() {
    super();
  }
  public void run() {
    long i = 0;
    while (true) {
      long premier = -1;
      if (verifierPremier(i)) {
        premier = i;
        NombrePremier objet = new NombrePremier(
                                       String.valueOf(premier));
      }
      i++;
    }
  }
  public boolean verifierPremier(long nombre) {
    if (nombre < 0)
      return false;
    else if (nombre < 4)
      return true;
    else {
      for (int i = 4; i <= nombre / 2; i++) {
        if (nombre != i && nombre % i == 0)
          return false;
      }
    }
    return true;
  }

  public static void main(String[] args) {
    Interruption thread = new Interruption();
    thread.start();
    while (thread.isAlive()) {
      try {
        Thread.sleep(500);
      }
      catch (InterruptedException e) {
      }
    }
  }
}

public class NombrePremier {
  private String valeur;
  public NombrePremier(String valeur) {
    this.valeur = valeur;
  }
  public String getValeur() {
    return this.valeur;
  }
  public void setValeur(String valeur) {
    this.valeur = valeur;
  }
  protected void finalize() throws Throwable {
    System.out.println("Invocation de la méthode finalize()");
    System.out.println("Contenu de l'objet : " + valeur);
    System.out.println("Nom du thread courant : "
                       + Thread.currentThread().getName());
    this.valeur = null;
  }
}
/* Affiche
...
Invocation de la méthode finalize()
Contenu de l'objet : 70879
Nom du thread courant : Finalizer
Invocation de la méthode finalize()
Contenu de l'objet : 72617
Nom du thread courant : Finalizer
Invocation de la méthode finalize()
Contenu de l'objet : 73453
Nom du thread courant : Finalizer
...
*/