Java - 多线程

Java - 多线程 首页 / Java入门教程 / Java - 多线程

Java是一种多线程编程语言,这意味着无涯教程可以使用Java开发多线程程序。多线程程序包含可以并发运行的两个或更多部分,每个部分可以同时处理不同的任务,最大限度地利用可用资源,特别是当您的计算机具有多个CPU时。

线程的生命周期

线程在其生命周期中经历不同阶段。如,一个线程诞生,启动,运行,然后死亡。下图显示了线程的完整生命周期。

Java Thread

以下是生命周期-的各个阶段

  • New                   - 新线程在新状态下开始其生命周期。它一直保持这种状态,直到程序启动线程。

  • Runnable          - 启动新生的线程后,该线程变为可运行。处于此状态的线程被视为正在执行其任务。

  • Waiting             - 有时一个线程在等待另一个线程执行任务时转换到等待状态。

  • Timed Waiting - 可运行线程可以在指定的时间间隔内进入定时等待状态。

  • Dead(死亡)       - 可运行线程在完成其任务或以其他方式终止时进入终止状态。

线程优先级

每个Java线程都有一个优先级,帮助操作系统确定调度线程的顺序。

Java线程优先级在MIN_PRIORITY(常量1)和MAX_PRIORITY(常量10)之间。默认情况下,每个线程都被赋予优先级NORM_PRIORITY(常量为5)。

优先级较高的线程对程序更重要,应该在优先级较低的线程之前分配处理器时间。然而,线程优先级不能保证线程执行的顺序,并且非常依赖于平台。

实现Runnable接口

如果您的类打算作为线程执行,那么您可以通过实现Runnable接口来实现这一点。您需要遵循三个基本步骤-

第1步  -  您需要实现由Runnable接口提供的run()方法。此方法为线程提供入口点,您将把完整的业务逻辑放在此方法中。以下是Run()方法-的简单语法

public void run( )

第2步  -  您将使用以下构造函数-化线程对象

Thread(Runnable threadObj, String threadName);

其中,threadObj是实现Runnable接口的类的,而threadName是为新线程指定的名称。

第3步  -  创建Thread 对象后,可以通过调用start()方法启动它,该方法执行对run()方法的调用。下面是Start()方法-的简单语法

void start();

下面是一个创建新线程并开始运行它的示例-

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            //Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

这将产生以下输出-

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

扩展Thread类

创建线程的第二种方法是使用以下两个简单步骤创建扩展Thread类的新类。这种方法在处理使用Thread类中的可用方法创建的多个线程时提供了更大的灵活性。

第1步  -  您将需要重写Thread类中可用的Run()方法。此方法为线程提供入口点,您将把完整的业务逻辑放在此方法中。以下是Run()方法-的简单语法

public void run( )

第2步  -  创建Thread 对象后,可以通过调用start()方法启动它,该方法执行对run()方法的调用。下面是Start()方法-的简单语法

void start( );

下面是为扩展线程-而重写的前面的程序

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            //Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

这将产生以下输出-

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

Thread 方法

下面是Thread类中可用的重要方法的列表。

Sr.No.Method & Remark
1

public void start()

在单独的执行路径中启动线程,然后调用此Thread对象的run()方法。

2

public void run()

如果此Thread 对象是使用单独的Runnable目标化的,则会在该Runnable对象上调用run()方法。

3

public final void setName(String Name)

更改Thread对象的名称。

4

public final void setPriority(int priority )

设置此Thread对象的优先级。可能的值介于1和10之间。

5

public final void setDaemon(Boolean On)

参数true表示该线程作为守护程序线程。

6

public final void join(Long Millisec)

当前线程在第二个线程上调用此方法,导致当前线程阻塞,直到第二个线程终止或经过指定的毫秒数。

7

public void interrupt()

中断此线程,如果由于某种原因而被阻止,则导致该线程继续执行。

8

public final boolean isAlive()

如果线程处于活动状态(即线程启动后但运行完成之前的任何时间),则返回true。

前面的方法是在特定的Thread对象上调用的。Thread类中的以下方法是静态的。调用其中一个静态方法在当前运行的线程上执行操作。

Sr.No.Method & Remark
1

public static void yield()

导致当前正在运行的线程让位给任何其他具有相同优先级的线程,这些线程正在等待调度。

2

public static void sleep(Long Millisec)

使当前运行的线程阻塞至少指定的毫秒数。

3

public static Boolean holdsLock(Object X)

如果当前线程持有给定对象 的锁,则返回true。

4

public static Thread currentThread()

返回对当前正在运行的线程的引用,该线程是调用此方法的线程。

5

public static void dumpStack()

打印当前正在运行的线程的堆栈跟踪,这在调试多线程应用程序时很有用。

下面的ThreadClassDemo程序演示了Thread类的其中一些方法。考虑实现可运行-的类DisplayMessage

//File Name : DisplayMessage.java
//Create a thread to implement Runnable

public class DisplayMessage implements Runnable {
   private String message;
   
   public DisplayMessage(String message) {
      this.message = message;
   }
   
   public void run() {
      while(true) {
         System.out.println(message);
      }
   }
}

下面是另一个扩展Thread类-的类

//File Name : GuessANumber.java
//Create a thread to extentd Thread

public class GuessANumber extends Thread {
   private int number;
   public GuessANumber(int number) {
      this.number = number;
   }
   
   public void run() {
      int counter = 0;
      int guess = 0;
      do {
         guess = (int) (Math.random() * 100 + 1);
         System.out.println(this.getName() + " guesses " + guess);
         counter++;
      } while(guess != number);
      System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
   }
}

下面是主程序,它利用了上面定义的类-

//File Name : ThreadClassDemo.java
public class ThreadClassDemo {

   public static void main(String [] args) {
      Runnable hello = new DisplayMessage("Hello");
      Thread thread1 = new Thread(hello);
      thread1.setDaemon(true);
      thread1.setName("hello");
      System.out.println("Starting hello thread...");
      thread1.start();
      
      Runnable bye = new DisplayMessage("Goodbye");
      Thread thread2 = new Thread(bye);
      thread2.setPriority(Thread.MIN_PRIORITY);
      thread2.setDaemon(true);
      System.out.println("Starting goodbye thread...");
      thread2.start();

      System.out.println("Starting thread3...");
      Thread thread3 = new GuessANumber(27);
      thread3.start();
      try {
         thread3.join();
      } catch (InterruptedException e) {
         System.out.println("Thread interrupted.");
      }
      System.out.println("Starting thread4...");
      Thread thread4 = new GuessANumber(75);
      
      thread4.start();
      System.out.println("main() is ending...");
   }
}

这将产生以下输出。你可以再试一次这个Example,每次都会得到不同的输出。

Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......

Java多线程概念

在用Java语言进行多线程编程时,您需要有以下非常方便的-概念

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

程序员进阶攻略 -〔胡峰〕

深入浅出计算机组成原理 -〔徐文浩〕

TypeScript开发实战 -〔梁宵〕

苏杰的产品创新课 -〔苏杰〕

分布式数据库30讲 -〔王磊〕

技术管理案例课 -〔许健〕

陶辉的网络协议集训班02期 -〔陶辉〕

容量保障核心技术与实战 -〔吴骏龙〕

Web 3.0入局攻略 -〔郭大治〕

好记忆不如烂笔头。留下您的足迹吧 :)