Java中线程终止和线程的常用方法

336 阅读4分钟

线程终止

线程终止是指线程的执行结束或者被强制终止。在Java中,线程终止有以下两种方式:

  1. 正常终止:当线程执行完所有的任务并正常退出时,线程就会终止。

  2. 异常终止:当线程因为未捕获的异常而终止时,线程就会以异常终止。

正常终止

正常终止是指当线程完成了所有的任务并正常退出时,线程就会终止。

这种方式可以通过以下两种方法实现:

run方法执行完成后,线程就会终止。

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        // 线程执行的任务  
    }  
}  
  
MyThread thread = new MyThread();  
thread.start();  // 启动线程 

通过调用Thread类的interrupt()方法,让线程中断并终止。

interrupt()方法中断线程,线程就会终止

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        try {  
            Thread.sleep(5000);  // 线程休眠5秒  
        } catch (InterruptedException e) {  
            System.out.println("线程被中断");  
        }  
    }  
}  
  
MyThread thread = new MyThread();  
thread.start();  // 启动线程  
thread.interrupt();  // 中断线程  

调用interrupt()方法并不会立即终止线程,而是会将线程的中断标志设置为true。如果在线程休眠期间调用了interrupt()方法,会抛出InterruptedException异常,并将中断标志清除。

异常终止

异常终止是指当线程因为未捕获的异常而终止时,线程就会以异常终止。

这种方式可以通过以下两种方法实现:

在run方法中抛出异常

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        throw new RuntimeException("线程异常终止");  
    }  
}  
  
MyThread thread = new MyThread();  
thread.start();  // 启动线程  
}  


在Thread.UncaughtExceptionHandler接口中捕获未捕获的异常

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        throw new RuntimeException("线程异常终止");  
    }  
}  

public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {  
    @Override  
    public void uncaughtException(Thread t, Throwable e) {  
        System.out.println(t.getName() + "线程异常终止:" + e.getMessage());  
    }  
}  
  
public class Main {  
    public static void main(String[] args) {  
        MyThread myThread = new MyThread();  
        myThread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());  
        myThread.start();  
    }  
}  

创建了一个MyThread类,其中的run方法抛出一个RuntimeException异常。然后,我们实现了一个MyUncaughtExceptionHandler类,它实现了Thread.UncaughtExceptionHandler接口,并重写了uncaughtException方法,当线程抛出未捕获的异常时,将异常信息打印出来。

在Main类的main方法中,我们创建了一个MyThread对象,并将其UncaughtExceptionHandler设置为MyUncaughtExceptionHandler。然后,我们启动线程。

当线程抛出未捕获的异常时,MyUncaughtExceptionHandler的uncaughtException方法将被调用,并打印异常信息。这样,我们就可以处理未捕获的异常了。

线程的常用方法

  1. start():启动线程。
  2. run():线程的运行方法,需要自行重写。
  3. join():等待线程终止。
  4. interrupt():中断线程。
  5. isInterrupted():判断线程是否已中断。
  6. sleep():线程休眠一段时间。
  7. yield():暂停当前线程,让其他线程执行。
  8. setPriority():设置线程的优先级。
  9. getName():获取线程名称。

start()

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        System.out.println("Thread is running.");  
    }  
}  
  
public class Main {  
    public static void main(String[] args) {  
        MyThread thread = new MyThread();  
        thread.start();  
    }  
}  

通过继承Thread类并重写run方法来实现多线程。使用start方法启动线程。

run()

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        System.out.println("Thread is running.");  
    }  
}  
  
public class Main {  
    public static void main(String[] args) {  
        MyThread thread = new MyThread();  
        thread.run();  
    }  
}

直接调用run方法并不会创建一个新的线程,而是在当前线程中执行run方法。

join()

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        System.out.println("Thread is running.");  
    }  
}  
  
public class Main {  
    public static void main(String[] args) throws InterruptedException {  
        MyThread thread = new MyThread();  
        thread.start();  
        thread.join();  
        System.out.println("Thread is terminated.");  
    }  
}  

使用join方法等待线程终止。在本例中,主线程等待MyThread线程终止后才能继续执行。

interrupt()

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            System.out.println("Thread is interrupted.");  
        }  
    }  
}  
  
public class Main {  
    public static void main(String[] args) {  
        MyThread thread = new MyThread();  
        thread.start();  
        thread.interrupt();  
    }  
}  

使用interrupt方法中断线程。在本例中,MyThread线程休眠1秒钟,主线程调用interrupt方法中断线程。

isInterrupted()

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        while (!isInterrupted()) {  
            System.out.println("Thread is running.");  
        }  
        System.out.println("Thread is interrupted.");  
    }  
}  
  
public class Main {  
    public static void main(String[] args) throws InterruptedException {  
        MyThread thread = new MyThread();  
        thread.start();  
        Thread.sleep(1000);  
        thread.interrupt();  
    }  
}  

使用isInterrupted方法判断线程是否已中断。在本例中,MyThread线程在不停地输出信息,直到被中断后输出“Thread is interrupted.”。

sleep()

方法签名为:

public static void sleep(long millis) throws InterruptedException 
public class SleepDemo {  
    public static void main(String[] args) {  
        Thread t = new Thread(() -> {  
            try {  
                System.out.println("线程开始休眠");  
                Thread.sleep(3000);  
                System.out.println("线程休眠结束");  
            } catch (InterruptedException e) {  
                System.out.println("线程被中断");  
            }  
        });  
        t.start();  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        t.interrupt();  
    }  
}

创建了一个新线程,使其在run()方法中调用sleep()方法休眠3秒钟。在主线程中,我们先让主线程休眠1秒钟,然后调用interrupt()方法中断新线程。当新线程被中断时,会抛出InterruptedException异常,我们在catch块中捕获该异常,并输出相应信息。    yield()方法

yield()

public class YieldTest {  
    public static void main(String[] args) {  
        Thread t1 = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                for (int i = 1; i <= 10; i++) {  
                    System.out.println("Thread1:" + i);  
                    Thread.yield();  
                }  
            }  
        });  
  
        Thread t2 = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                for (int i = 1; i <= 10; i++) {  
                    System.out.println("Thread2:" + i);  
                    Thread.yield();  
                }  
            }  
        });  
  
        t1.start();  
        t2.start();  
    }  
}

setPriority()

public class PriorityTest {  
    public static void main(String[] args) {  
        Thread t1 = new Thread(new MyRunnable());  
        Thread t2 = new Thread(new MyRunnable());  
  
        t1.setPriority(Thread.MAX_PRIORITY);  
        t2.setPriority(Thread.MIN_PRIORITY);  
  
        t1.start();  
        t2.start();  
    }  
  
    static class MyRunnable implements Runnable {  
        @Override  
        public void run() {  
            for (int i = 1; i <= 10; i++) {  
                System.out.println(Thread.currentThread().getName() + ":" + i);  
            }  
        }  
    }  
}

getName()

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        System.out.println("当前线程的名称为:" + getName());  
    }  
}  
  
public class Main {  
    public static void main(String[] args) {  
        MyThread myThread = new MyThread();  
        myThread.start();  
        System.out.println("当前主线程的名称为:" + Thread.currentThread().getName());  
    }  
}  

创建了一个继承自 Thread 类的 MyThread 子类。在 run() 方法中,我们使用 getName() 方法获取当前线程的名称并输出。