【JAVA】总结线程Thread的基本用法

发布于:2022-12-21 ⋅ 阅读:(219) ⋅ 点赞:(0)

    目录~~~

1.线程创建

2.线程中断

3.线程等待

4.线程休眠

5.获取线程实例


线程创建

线程创建的方式有很多种,接下来介绍5种常见的线程创建方式

1.实现Thread子类,重写run方法

//实现Thread子类来创建线程(继承Thread)

class MyThread extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("hello world");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        t.start();//当start开始调用,才算创建了线程

        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

2.实现Runnable接口,重写run方法

//实现Runnable接口来创建线程
class MyRunnable implements Runnable{
    @Override
    public void run() {
        while(true){
            System.out.println("hello hi");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable runnable = new MyRunnable();
        Thread t = new Thread(runnable);//使用这个方法创建线程可以将线程与线程工作本身分开
        t.start();

        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

3.用匿名内部类来实现Thread子类

//使用匿名内部类来实现Thread子类来创建线程
public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
                while (true){
                    System.out.println("hello hahaha");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();

        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

4.用匿名内部类来实现Runnable接口

//使用匿名内部类实现Runnable接口来创建线程
public class Demo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable(){
            @Override
            public void run() {
                while (true){
                    System.out.println("+++++++++++++++++");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        t.start();

        while (true){
            System.out.println("*********************");
            Thread.sleep(1000);
        }
    }
}

5.lambda表达式(推荐写法)

//lambda表达式
public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (true){
                System.out.println("hello bbb");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.start();

        while (true){
            System.out.println("**************");
            Thread.sleep(1000);
        }
    }

注:

1.run方法里的代码是程序员给线程安排任务

2.要想真正创建线程,不要忘了start方法的调用,只有start调用了,线程才会真正被创建并且运行


线程中断

有时候我们在写代码的时候,会有一些不那么重要的数据运行计算,当我们不想浪费时间等待的时候,我们可以将线程“中断”,这里的中断并不是说在线程运行是直接打断程序,而是加速线程的运行,使线程尽快结束,即让run尽快结束~

(不是打断正在运行的线程,而是到时间线程自己停下)

原理就是在程序中设置一个标志位,当运行到标志位设置的时间时,线程结束

我们有两种手段来实现线程中断

1.自己定义标志位

public class Demo3 {
    public static boolean isQuit = true;
    
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (isQuit){
                System.out.println("hello Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("线程t结束了");
        });
        t.start();

        //让主线程3秒后改变isQuit
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        isQuit = false;
        System.out.println("让线程t结束");
    }
}

自己定义了一个isQuit标志位,开始为标志位为true,while可以循环打印,在main主线程中设置了3秒后isQuit为false,则线程t在3秒后执行结束

2.使用标准库中自带的标志位

Thread.currentThread().isInterrupted()

currentThread()这是Thread类的静态方法,通过这个方法就可以拿到当前线程的实例(拿到当前线程对应的Thread对象)

isInterrupted()这个方法在判断标志位为true还是为false

简单来说就是在判定此时这个线程是在运行还是已经结束,正在运行为true,结束为false,因此用来作为while循环的判定标志,从而使循环结束

public class Demo4 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    //throw new RuntimeException(e);
                    break;
                }
            }
            System.out.println("线程t结束了");
        });
        t.start();

        //让主线程3秒后改变isQuit
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        t.interrupt();
        System.out.println("让线程t结束");
    }
}

而interrupt方法调用后会出现两种结果

1.线程如果在运行,则会设置标志位为true

2.线程如果处于阻塞状态,则设置成true的标志位会被清除,然后循环并并不会被终止,线程继续运行


线程等待

这里介绍一下前台线程与后台线程,一个进程里有多个前台进程和多个后台进程,他们并发执行,当前台进程全部结束后,无论后台线程是否还在工作,都会被停止,进程结束,反过来,如果后台线程全部结束,而还剩哪怕一个前台线程在运行中,进程也不会结束,也会等到最后一个前台进程结束后进程才会结束,

简单来说就是,进程跟着前台进程走,前台结束,进程结束,不管后台此时怎么样

那么问题来了,由于线程会抢占式执行,当线程们就绪时,由系统内核来决定哪个线程先执行,这是不确定的,所以有时候会出现假如两个线程针对同一个变量进行操作,其中一个线程还没计算完自己的工作,另外一个线程就开始把一个不完整的结果来计算,势必会导致结果出问题,

所以两个线程,我们先让线程1做好自己的工作,另外一个线程2等待线程1结束后才继续执行

综上所述,我们用join方法来实现线程的等待,谁调用了join,谁就先执行,执行完毕后,不调用join的线程才继续执行

比如我想用线程t实现5次打印后,main线程才开始运行,如果不调用join等待线程t先打印完,由于线程并发执行,main会同时运行,t还没结束,main就先结束了

public class Demo7 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
           for (int i = 0; i < 5; i++){
               System.out.println("hello Thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        thread.start();
        
        System.out.println("main线程结束了");
    }
}

调用join

 

则main会阻塞等待,直到t结束后,main才结束


 线程休眠

这玩意很简单,就是Thread中的sleep方法,以毫秒级来运行程序,比如你想循环打印并且每隔1秒打印一次,则可以调用sleep,调用sleep会出现受查异常,手动try就行了


获取线程实例

在上文标志位那里第二个使用标准库的标志位中的while循环里的判断

Thread.currentThread()

调用这个静态方法可以获取当前线程实例

以下是获取线程的属性

public class Demo2 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"自定义线程");
        t.start();

        System.out.println(t.getId());//获取线程ID
        System.out.println(t.getName());//名字
        System.out.println(t.getPriority());//优先级
        System.out.println(t.getState());//状态
        System.out.println(t.isDaemon());//是否后台
        System.out.println(t.isAlive());//是否存活
        System.out.println(t.isInterrupted());//是否被打断
    }
}

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到