Java Thread线程类相关方法调用示例

x33g5p2x  于2021-08-19 转载在 Java  
字(11.1k)|赞(0)|评价(0)|浏览(263)

在这篇文章中,我们将通过实例来了解Thread类和它的方法。
Thread创建了一个新的执行线程。它实现了Runnable接口。Java虚拟机允许一个应用程序有多个执行线程同时运行。

###线程类构造函数

  1. Thread() - 分配一个新的线程对象。
  2. Thread(Runnable target) - 分配一个新的线程对象。
  3. Thread(Runnable target, String name)- 分配一个新的线程对象。
  4. Thread(String name)-分配一个新的线程对象。
  5. Thread(ThreadGroup group, Runnable target)-分配一个新的Thread对象。
  6. Thread(ThreadGroup group, Runnable target, String name) - 分配一个新的线程对象,使其将目标作为其运行对象,将指定的名称作为其名称,并属于该组所指的线程组。
  7. Thread(ThreadGroup group, Runnable target, String name, long stackSize) - 分配一个新的Thread对象,使其将目标作为其运行对象,将指定的名称作为其名称,并且属于group所指的线程组,并且有指定的堆栈大小。
  8. Thread(ThreadGroup group, String name)- 分配一个新的线程对象。
    ###线程类方法

类图显示了java.lang.Thread类API/方法的列表。

###线程类方法与实例

让我们来演示一下java.lang.Thread类的几个重要方法的用法。

Thread.sleep()方法

Thread.sleep使当前线程在指定的时间内暂停执行。这是一种有效的手段,可以为应用程序的其他线程或可能在计算机系统上运行的其他应用程序提供处理器时间。

Thread.sleep()方法实例
在这个例子中,我们已经创建并启动了两个线程thread1和thread2。请注意,我们在本例中使用了sleep()方法的两个重载版本。

Thread.sleep(1000);
Thread.sleep(1000, 500);
//*/*
/* thread sleep method examples
/* @author Ramesh fadatare
/*
/*/
public class ThreadSleepExample {
  public static void main(final String[] args) {
      System.out.println("Thread main started");
      final Thread thread1 = new Thread(new WorkerThread());
      thread1.setName("WorkerThread 1");
      final Thread thread2 = new Thread(new WorkerThread());
      thread1.setName("WorkerThread 2");
      thread1.start();
      thread2.start();
      System.out.println("Thread main ended");
  }
}

class WorkerThread implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
        try {
            Thread.sleep(1000);
            Thread.sleep(1000, 500);
            System.out.println("[" + Thread.currentThread().getName() + "] Message " + i);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
      }
   }
}

输出。

Thread main started
Thread main ended
[WorkerThread 2] Message 0
[Thread-1] Message 0
[WorkerThread 2] Message 1
[Thread-1] Message 1
[WorkerThread 2] Message 2
[Thread-1] Message 2
[WorkerThread 2] Message 3
[Thread-1] Message 3
[WorkerThread 2] Message 4
[Thread-1] Message 4

请注意,*sleep()*方法会抛出InterruptedException异常,当另一个线程在睡眠状态下中断了当前线程时。

###线程join()方法

join()方法会等待一个线程死亡。换句话说,它使当前运行的线程停止执行,直到它加入的线程完成其任务。

线程join()方法的例子。 我们将首先创建一个任务,它将计算1-5个数字的总和(保持在for循环中)。在主线程中,我们创建4个任务。

final Task task1 = new Task(500l);
final Task task2 = new Task(1000l);
final Task task3 = new Task(2000l);
final Task task4 = new Task(50l);

现在,让我们创建4个线程来运行上述4个任务。

final Thread thread1 = new Thread(task1); 
final Thread thread2 = new Thread(task2);
final Thread thread3 = new Thread(task3);
final Thread thread4 = new Thread(task4);

为每个线程指定名称并启动所有4个线程。

thread1.setName("thread-1");
thread2.setName("thread-2");
thread3.setName("thread-3");
thread4.setName("thread-4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();

在这个例子中,当目标线程完成求和时,调用者线程(main)会醒来并调用*task.getSum()*方法,由于目标线程已经完成了它的工作,它肯定会包含总和。
任务4有一个小的睡眠时间,因此它在其他线程之前完成了总和。因此,主线程调用thread4.join(),但由于thread4已经完成,所以立即返回到它的执行。

//*/*
/* This class demonstrate the how join method works with an example. 
/* @author Ramesh Fadatare
/*
/*/
public class ThreadJoinExample {
    public static void main(final String[] args) throws InterruptedException {
        System.out.println("Thread main started");
  
       final Task task1 = new Task(500l);
       final Task task2 = new Task(1000l);
       final Task task3 = new Task(2000l);
       final Task task4 = new Task(50l);
       final Thread thread1 = new Thread(task1); 
       final Thread thread2 = new Thread(task2);
       final Thread thread3 = new Thread(task3);
       final Thread thread4 = new Thread(task4); 
       thread1.setName("thread-1");
       thread2.setName("thread-2");
       thread3.setName("thread-3");
       thread4.setName("thread-4");
       thread1.start();
       thread2.start();
       thread3.start();
       thread4.start();
  
       System.out.println("[" + Thread.currentThread().getName() + "] waiting for " + thread1.getName());
       thread1.join();
       System.out.println(thread1.getName() + " finished! Result: " + task1.getSum());
  
       System.out.println("[" + Thread.currentThread().getName() + "] waiting for " + thread2.getName());
       thread2.join();
       System.out.println(thread2.getName() + " finished! Result: " + task2.getSum());
  
      System.out.println("[" + Thread.currentThread().getName() + "] waiting for " + thread3.getName());
      thread3.join();
      System.out.println(thread3.getName() + " finished! Result: " + task3.getSum());
  
     // As thread-4 already finished (smaller sleep time), the join call only immediately
     // returns the control to the caller thread
     System.out.println("[" + Thread.currentThread().getName() + "] waiting for " + thread4.getName());
     thread4.join();
     System.out.println(thread4.getName() + " finished! Result: " + task4.getSum());
  
     System.out.println("Thread main finished");
   }
}

class Task implements Runnable {
     private long sleep; 
     private int sum;
 
     public Task(final long sleep) {
         this.sleep = sleep;
     }
 
     @Override
     public void run() {
         for (int i = 1; i <= 5; i++) {
              System.out.println("[" + Thread.currentThread().getName() + "] Adding " + i);
              sum += i;
              try {
                  Thread.sleep(sleep);
              } catch (final InterruptedException e) {
                  e.printStackTrace();
              }
         }
     }
 
     public int getSum() {
         return this.sum;
     }
}

输出:

Thread main started
[thread-1] Adding 1
[thread-2] Adding 1
[thread-3] Adding 1
[main] waiting for thread-1
[thread-4] Adding 1
[thread-4] Adding 2
[thread-4] Adding 3
[thread-4] Adding 4
[thread-4] Adding 5
[thread-1] Adding 2
[thread-1] Adding 3
[thread-2] Adding 2
[thread-1] Adding 4
[thread-1] Adding 5
[thread-3] Adding 2
[thread-2] Adding 3
thread-1 finished! Result: 15
[main] waiting for thread-2
[thread-2] Adding 4
[thread-2] Adding 5
[thread-3] Adding 3
thread-2 finished! Result: 15
[main] waiting for thread-3
[thread-3] Adding 4
[thread-3] Adding 5
thread-3 finished! Result: 15
[main] waiting for thread-4
thread-4 finished! Result: 15
Thread main finished

注意,输出,main()线程最后完成了它的执行。试着通过观察一个输出来理解这个例子。
join()方法抛出一个InterruptedException - 如果有任何线程打断了当前线程。当这个异常被抛出时,当前线程的中断状态被清除了。

Thread.interrupt()方法

中断是对一个线程的指示,它应该停止它正在做的事情,做一些别的事情。线程对中断的具体响应方式由程序员决定,但线程终止是非常常见的。

java.lang线程类提供了三个中断()方法来正确处理中断。

  1. void interrupt() - 中断这个线程。
  2. static boolean interrupted() - 测试当前线程是否已经被中断。
  3. boolean isInterrupted() - 测试这个线程是否被中断。
    Thread.interrupt()方法示例
public class TerminateTaskUsingThreadAPI {

 public static void main(final String[] args) {

  System.out.println("Thread main started");

  final Task task = new Task();
  final Thread thread = new Thread(task);
  thread.start();

  thread.interrupt();

  System.out.println("Thread main finished");
 }
}

class Task implements Runnable {
 @Override
 public void run() {
  for (int i = 0; i < 5; i++) {
   System.out.println("[" + Thread.currentThread().getName() + "] Message " + i);

   if (Thread.interrupted()) {
    System.out.println("This thread was interruped by someone calling this Thread.interrupt()");
    System.out.println("Cancelling task running in thread " + Thread.currentThread().getName());
    System.out.println("After Thread.interrupted() call, JVM reset the interrupted value to: " + Thread.interrupted());
    break;
   }
  }
 }
}

输出:

Thread main started
Thread main finished
[Thread-0] Message 0
This thread was interruped by someone calling this Thread.interrupt()
Cancelling task running in thread Thread-0
After Thread.interrupted() call, JVM reset the interrupted value to: false

注意,这里是任务被终止,而不是线程被终止。

Thread is isAlive方法

java.lang.Thread类提供了*isAlive()*方法来测试这个线程是否活着。如果一个线程已经被启动并且还没有死亡,那么它就是活的。

Thread is isAlive方法示例

  1. 让我们创建两个线程
final Thread thread1 = new Thread(new MyTask());
final Thread thread2 = new Thread(new MyTask());
  1. 在用start()方法启动线程之前,只需打印检查线程是否活着。
System.out.println("Thread1 is alive? " + thread1.isAlive());
System.out.println("Thread2 is alive? " + thread2.isAlive());
  1. 启动线程并再次检查线程是否存活
thread1.start();
thread2.start();

while (thread1.isAlive() || thread2.isAlive()) {
 System.out.println("Thread1 is alive? " + thread1.isAlive());
 System.out.println("Thread2 is alive? " + thread2.isAlive());
 Thread.sleep(500l);
}

让我们把所有的东西放在一起,完整的程序。

public class CheckIfThreadIsAliveUsingThreadAPI {

 public static void main(final String[] args) throws InterruptedException {

  System.out.println("Thread main started");

  final Thread thread1 = new Thread(new MyTask());
  final Thread thread2 = new Thread(new MyTask());

  System.out.println("Thread1 is alive? " + thread1.isAlive());
  System.out.println("Thread2 is alive? " + thread2.isAlive());

  thread1.start();
  thread2.start();

  while (thread1.isAlive() || thread2.isAlive()) {
   System.out.println("Thread1 is alive? " + thread1.isAlive());
   System.out.println("Thread2 is alive? " + thread2.isAlive());
   Thread.sleep(500l);
  }

  System.out.println("Thread1 is alive? " + thread1.isAlive());
  System.out.println("Thread2 is alive? " + thread2.isAlive());
  
  System.out.println("Thread main finished");
 }
}

class MyTask implements Runnable {
 @Override
 public void run() {
  for (int i = 0; i < 5; i++) {
   System.out.println("[" + Thread.currentThread().getName() + "] Message " + i);
   try {
    Thread.sleep(200);
   } catch (final InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

输出。

Thread main started
Thread1 is alive? false
Thread2 is alive? false
Thread1 is alive? true
Thread2 is alive? true
[Thread-0] Message 0
[Thread-1] Message 0
[Thread-1] Message 1
[Thread-0] Message 1
[Thread-1] Message 2
[Thread-0] Message 2
Thread1 is alive? true
Thread2 is alive? true
[Thread-0] Message 3
[Thread-1] Message 3
[Thread-1] Message 4
[Thread-0] Message 4
Thread1 is alive? false
Thread2 is alive? false
Thread main finished

线程setPriority()方法

每个线程都有一个优先级。优先级用1到10之间的数字表示。在大多数情况下,线程调度器会根据线程的优先级来调度它们(被称为抢占式调度)。但这并不保证,因为这取决于JVM的规范,它选择哪种调度方式。

在Thread类中定义了三个常量。

1.公共静态int MIN_PRIORITY
1.公共静态int NORM_PRIORITY

  1. public static int MAX_PRIORITY 线程的默认优先级是5(NORM_PRIORITY)。MIN_PRIORITY的值是1,MAX_PRIORITY的值是10。
    为线程设置优先级示例
public class ThreadPriorityExample {
 public static void main(final String[] args) {
  final Runnable runnable = () -> {
    System.out.println("Running thread name : " + Thread.currentThread().getName() +  
      " and it's priority : " + Thread.currentThread().getPriority());
   
  };
  
  final Thread thread1 = new Thread(runnable);
  final Thread thread2 = new Thread(runnable);
  final Thread thread3 = new Thread(runnable);
  final Thread thread4 = new Thread(runnable);
  thread1.setPriority(Thread.MIN_PRIORITY);
  thread2.setPriority(Thread.NORM_PRIORITY);
  thread3.setPriority(Thread.MAX_PRIORITY);
  thread4.setPriority(2);
  
  thread1.start();
  thread2.start();
  thread3.start();
  thread4.start();
 }
}

输出:

Running thread name : Thread-0 and it's priority : 1
Running thread name : Thread-1 and it's priority : 5
Running thread name : Thread-2 and it's priority : 10
Running thread name : Thread-3 and it's priority : 2

Thread setName()方法

java.lang.Thread类提供了改变和获取线程名称的方法。默认情况下,每个线程都有一个名字,即thread-0,thread-1等等。通过使用setName()方法,我们可以改变线程的名称。setName()和getName()方法的语法给出如下。

  • public String getName(): 用来返回线程的名称。
  • public void setName(String name):用于改变线程的名称。
    线程类提供了一个静态的currentThread() - 返回当前执行的线程对象的引用。

命名一个线程的例子

//*/*
/*  Thread naming example using Thread class.
/*  @author Ramesh fadatare
/*/*/

public class ThreadExample {
 
 public static void main(final String[] args) {
  
  System.out.println("Thread main started");

  final Thread thread1 = new WorkerThread();
  thread1.setName("WorkerThread1");
  
  final Thread thread2 = new WorkerThread();
  thread2.setName("WorkerThread2");
  
  final Thread thread3 = new WorkerThread();
  thread3.setName("WorkerThread3");
  
  final Thread thread4 = new WorkerThread();
  thread4.setName("WorkerThread4");
  
  thread1.start();
  thread2.start();
  thread3.start();
  thread4.start();
  
  System.out.println("Thread main finished");
 }
}

class WorkerThread extends Thread {
 
 @Override
 public void run() {
  System.out.println("Thread Name :: " + Thread.currentThread().getName());
 }
}

输出。

Thread main started
Thread Name :: WorkerThread1
Thread Name :: WorkerThread2
Thread Name :: WorkerThread3
Thread main finished
Thread Name :: WorkerThread4

###引用

https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html

相关文章

微信公众号

最新文章

更多