【Java多线程】Thread类的基本用法

简介: 【Java多线程】Thread类的基本用法

Thread类




1、创建线程

线程的创建方法一共有五种,其中lambda表达式的创建方式最为常用,这里简单的给大家介绍一下这五种创建。


1.1、继承 Thread,重写run

class MyThread2 extends Thread {   //创建一个类继承Thread,并重写run
    @Override
    public void run() {   
        System.out.println("hello thread");
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        Thread t = new MyThread2();   //创建MyThread类的实例
        t.start();   //调用start方法启动线程
    }
}

1.2、实现 Runnable,重写run

Thread(Runnable target),使用runnable对象创建线程对象。
class MyThread3 implements Runnable {   //实现Runnable接口
    @Override
    public void run() {
        System.out.println("hello runnable");
    }
}
public class ThreadDemo3 {
    public static void main(String[] args) {
        Runnable runnable = new MyThread3();  //创建runnable对象
        Thread t = new Thread(runnable);   //将runnable对象作为target参数
        t.start();   //start启动线程
    }
}

1.3、使用匿名内部类,继承 Thread,重写run

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new Thread() {   //继承thread类的匿名内部类
            @Override
            public void run() {
                System.out.println("hello thread");
            }
        };
        t.start();
    }
}

1.4、使用匿名内部类,实现 Runnable,重写run

public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {   //实现Runnable接口的匿名内部类
            @Override
            public void run() {
                System.out.println("hello runnable");
            }
        });
        t.start();
    }
}

1.5、使用 lambda 表达式(最常用)

public class ThreadDemo6 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {   //实现Runnable接口重写run的lambda写法【推荐使用】
            System.out.println("hello thread");
        });
        t.start();
    }
}

2、终止线程

有时我们需要让正在执行的线程终止,为了让线程能够停止,需要添加一些机制。


2.1、通过共享的标记来进行沟通

public class ThreadInterrupt {
       
    public static boolean isQuit = false;   //设置标志位isQuit充当控制开关
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (!isQuit) {    //控制while终止
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);   //让每个打印间隔1秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程执行完毕");
        });
        t.start();
        Thread.sleep(3000);   //sleep睡眠3秒后再修改标志位
        isQuit = true;
    }
}


2.2、调用 interrupt() 方法来通知

       使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标识位。


       其中,Thread.currentThread() 表示获取当前线程实例,类似于 this 。而这里没有直接使用this是因为此处的Thread线程使用的是匿名内部类,无法通过this获取当前实例。


       最后使用 interrupt() 进行终止线程。


 

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);   //让每个打印间隔1秒
                } catch (InterruptedException e) {
                    break;   //注意此处需要添加break,因为sleep会清空interrupted标志位
                }
            }
            System.out.println("线程执行完毕");
        });
        t.start();
        Thread.sleep(3000);   //sleep睡眠3秒后再调用interrupt终止线程
        t.interrupt();
    }


3、等待线程

多个线程的执行顺序是不确定的(随机调度,抢占式执行)


虽然线程底层的调度是随机的,但是可以在应用程序中,通过一些api,来影响到线程的调度顺序使用join就是其中一种方式,join()方法可以确定线程的结束顺序。



 

public static void main(String[] args) {
        Thread t1 = new Thread(() -> {   
            System.out.println("hello thread1");
        });
        Thread t2 = new Thread(() -> {   
            System.out.println("hello thread2");
        });
        t1.start();   //此时t1线程开始执行
        t1.join();    //等待t1结束后再执行下面代码
        t2.start();   //此时t2线程开始执行
        t2.join();    //等待t2结束后再执行下面代码
        System.out.println("hello main");   //最后执行main主线程中的打印
    }

【谁调用,谁等待】main方法中调用t.join(),main主线程就阻塞等待t线程结束,再继续执行。


典型的使用场景:

使用多个线程并发进行一系列计算,用一个线程阻塞等待上述计算线程,等到所有的线程都计算完了,最终这个线程汇总结果。


4、获取线程实例

有两种获取线程实例的方法,一种是 this ,另一种是 Thread.currentThread() 。


其中需要注意的是:this不能使用到匿名内部类中,因此匿名内部类只能通过Thread.currentThread() 来获取实例。


class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread :"+this.getName());   //使用this直接获取实例
    }
}
public class GetThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            Thread thread = Thread.currentThread();   //匿名内部类中通过currentThread获取实例
            System.out.println("t1线程中: "+thread.getName());
        });
        Thread t2 = new MyThread();
       
        t1.start();
        t1.join();
        t2.start();
    }
}

   


目录
相关文章
|
8月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
372 4
|
8月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
385 5
|
8月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
481 5
|
8月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
413 1
|
8月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
521 1
|
8月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
338 0
|
8月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
388 1
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
254 7
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
1145 58
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
361 3