【多线程】Thread类的用法

文章目录

    • [1. Thread类的创建](#1. Thread类的创建)
      • [1.1 自己创建类继承Thread类](#1.1 自己创建类继承Thread类)
      • [1.2 实现Runnable接口](#1.2 实现Runnable接口)
      • [1.3 使用匿名内部类创建Thread子类对象](#1.3 使用匿名内部类创建Thread子类对象)
      • [1.4 使用匿名内部类创建Runnable子类对象](#1.4 使用匿名内部类创建Runnable子类对象)
      • [1.5 使用lambda创建](#1.5 使用lambda创建)
    • [2. Thread常见的构造方法](#2. Thread常见的构造方法)
      • [2.1 Thread()](#2.1 Thread())
      • [2.2 Thread(Runnable target)](#2.2 Thread(Runnable target))
      • [2.3 Thread(String name)](#2.3 Thread(String name))
      • [2.4 Thread(Runnable target, String name)](#2.4 Thread(Runnable target, String name))
    • [3. Thread常见的属性](#3. Thread常见的属性)
    • [4. 线程的使用](#4. 线程的使用)
      • [4.1 启动线程](#4.1 启动线程)
      • [4.2 中断线程](#4.2 中断线程)
      • [4.3 等待线程](#4.3 等待线程)
      • [4.4 休眠线程](#4.4 休眠线程)

1. Thread类的创建

1.1 自己创建类继承Thread类

java 复制代码
package Thread;

//继承Thread类实现线程
class MyThread extends Thread{
    @Override
    public void run() {
            System.out.println("hello run");
    }
}
public class Dome1 {
    public static void main(String[] args){
    	//创建线程
        MyThread myThread = new MyThread();
        //启动线程
        myThread.start();
    }
}

1.2 实现Runnable接口

java 复制代码
//使用Runnable的方式创建线程
class MyRunnable implements Runnable{
    @Override
    public void run() {
            System.out.println("hello run");
    }
} 
public class Dome2 {
    public static void main(String[] args){
    	//创建线程
        MyRunnable myRunnable = new MyRunnable();
        Thread t = new Thread(myRunnable);
        //启动
        t.start();
    }
}

1.3 使用匿名内部类创建Thread子类对象

java 复制代码
//通过匿名内部类的方式创建线程
public class Dome3 {
    public static void main(String[] args) {
    	//创建线程
        Thread t = new Thread(){
            @Override
            public void run() {
                    System.out.println("hello run");
            }
        };
        //启动线程
        t.start();
    }
}

1.4 使用匿名内部类创建Runnable子类对象

java 复制代码
//使用匿名内部类创建Runnable子类对象
public class Dome4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                    System.out.println("hello run");
            }
        });
        t.start();
}

1.5 使用lambda创建

java 复制代码
//lambda实现线程
public class Dome5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread( () -> {
                System.out.println("hello run");
        });
        t.start();
    }
}

2. Thread常见的构造方法

2.1 Thread()

java 复制代码
//创建Thread对象
Thread t = new Thread();

2.2 Thread(Runnable target)

java 复制代码
//使用Runnable对象创建线程对象
Thread t = new Thread(new Runnable);

2.3 Thread(String name)

java 复制代码
//为这个线程命名
Thread t = new Thread("名字");

2.4 Thread(Runnable target, String name)

java 复制代码
//使用Runnable对象创建线程对象并命名
Thraed t = new Thread(new Runnable,"名字");

3. Thread常见的属性

属性 获取方法
ID getId()
name getName()
状态 getState()
优先级 getPriority()
是否为后台线程 isDaemon()
是否存活 isAlive()
是否中断 isInterrupted()
java 复制代码
public class Test4 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            //Thread.currentThread调用当前线程对象,相当于t,这个时候t还未初始化成功,不能直接使用
            System.out.println("ID: " + Thread.currentThread().getId());
            System.out.println("name: " + Thread.currentThread().getName());
            System.out.println("状态: " + Thread.currentThread().getState());
            System.out.println("优先级: " + Thread.currentThread().getPriority());
            System.out.println("是否为后台线程: "  + Thread.currentThread().isDaemon());
            System.out.println("是否存活: " + Thread.currentThread().isAlive());
            System.out.println("是否中断: " + Thread.currentThread().isInterrupted());
        });
        t.start();
    }
}

注意:

  1. ID 是线程的唯一标识,不同线程不会重复
  2. 名称是各种调试工具用到
  3. 状态表示线程当前所处的一个情况,下面我们会进一步说明
  4. 优先级高的线程理论上来说更容易被调度到
  5. 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
  6. 是否存活,即简单的理解,为 run 方法是否运行结束了

4. 线程的使用

4.1 启动线程

前面我们已经知道了线程的创建,构造等方法,但这些其实都是准备工作,还没有真正的从底层创建出一个线程,只有调用start方法够才算真正的创建成功线程。
//直接调用就可以 t.start()

4.2 中断线程

当线程启动的时候,有时里面是循环,这时线程便不会停止,我们便要想办法中断线程。中断线程有个简单的方法直接使用Thread.stop()方法,但是,这种方法是unsafe,而且基本上已经deprecated。

所以我们调用interrupt()方法进行停止线程,但它并不会直接停止线程,而是对线程内进行标记,标记为Boolean类的true。这个时候我们再调用下面两个方法。
public static boolean interruputed();测试线程是否为中断状态,还执行后会标记清除为false。
public boolean isInterputed();测试线程是否为中断状态,但不清除标记。

添加标志符进行中断:

java 复制代码
//中断线程,添加标志位
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
        	//
           while(!Thread.currentThread().isInterrupted()){
               System.out.println(Thread.currentThread().getName());
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
//                   e.printStackTrace();
                   break;
               }
           }
        });
        //启动线程
        t1.start();
        //休眠3秒
        Thread.sleep(3000);
        t1.interrupt();
    }
}

注意:

如果休眠中中断线程,则会异常,反之,也是。

java 复制代码
//中断线程,添加标志位
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
//           while(!Thread.currentThread().isInterrupted()){
               try {
                   Thread.sleep(100000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
                   System.out.println("异常!");
               }
//           }
            System.out.println("end!");
        });
        t1.start();
        Thread.sleep(3000);
        t1.interrupt();
        System.out.println(t1.isInterrupted());
        System.out.println(Thread.interrupted());
    }
}

4.3 等待线程

方法 说明
join() 等待线程结束
join(long millis) 等待线程结束,最多等待millis毫秒
join(long millis,int nanos) 和2相比更加的精确

当我们同时启动几个线程,由于线程启动时随机无序的,我们无法得知谁先结束,这个时候就可以使用join方法让线程等待。

例如:当我们想让张三先上班,等张三上班结束,李四接班,那么我们就可以写出下面代码。

java 复制代码
public class Test5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println(Thread.currentThread().getName() + "在上班");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e ){
                    break;
                }
            }
        },"张三");
        Thread t2 = new Thread(() -> {
           while(!Thread.currentThread().isInterrupted()){
               System.out.println(Thread.currentThread().getName() + "在上班");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   break;
               }
           }
        },"李四");
        System.out.println("监督张三");
        t1.start();
        Thread.sleep(3000);
        t1.interrupt();
        t1.join();
        System.out.println("监督李四");
        t2.start();
        Thread.sleep(3000);
        t2.interrupt();
        t2.join();
    }
}

4.4 休眠线程

线程在执行的时候是非常快的,这个时候我们就可以让线程执行一次后就休眠一定时间,便于更好的观察。

上面代码中我们也多次用到。

java 复制代码
Thread.sleep(long millis),里面millis单位是毫秒。
相关推荐
啾啾Fun12 分钟前
Java反射操作百倍性能优化
java·性能优化·反射·缓存思想
20岁30年经验的码农19 分钟前
若依微服务Openfeign接口调用超时问题
java·微服务·架构
曲莫终27 分钟前
SpEl表达式之强大的集合选择(Collection Selection)和集合投影(Collection Projection)
java·spring boot·spring
ajassi200044 分钟前
开源 java android app 开发(十二)封库.aar
android·java·linux·开源
q567315231 小时前
Java使用Selenium反爬虫优化方案
java·开发语言·分布式·爬虫·selenium
kaikaile19951 小时前
解密Spring Boot:深入理解条件装配与条件注解
java·spring boot·spring
守护者1701 小时前
JAVA学习-练习试用Java实现“一个词频统计工具 :读取文本文件,统计并输出每个单词的频率”
java·学习
bing_1581 小时前
Spring Boot 中ConditionalOnClass、ConditionalOnMissingBean 注解详解
java·spring boot·后端
ergdfhgerty1 小时前
斐讯N1部署Armbian与CasaOS实现远程存储管理
java·docker
勤奋的知更鸟2 小时前
Java性能测试工具列举
java·开发语言·测试工具