Java基础进阶线程中的常用方法

简介: Java基础进阶线程中的常用方法

一、获取线程的名字


String name = 线程对象.getName();

修改线程对象的名字

线程对象.setName("线程名字");

当线程没有设置名字的时候,默认的名字有什么规律?(了解一下)

   Thread-0

   Thread-1

   Thread-2

   Thread-3


二、获取当前线程对象


Thread t = Thread.currentThread();

返回值t就是当前线程。


示例代码01:


public class ThreadTest05 {
    public static void doSome(){
        //这样就不行了
        //this.getName();
        //super.getName();
        // 但是这样可以
        String name = Thread.currentThread().getName();
        System.out.println("-->" + name);
    }
    public static void main(String[] args) {
        //创建分支线程对象
        MyThread2 t1 = new MyThread2();
        //调用doSome方法()
        ThreadTest05.doSome();
        //获取当前的线程对象
        // currentThread就是当前线程对象
        // 这个代码出现在main方法当中,所以当前线程就是主线程。
        Thread currentThread = Thread.currentThread();
        System.out.println(currentThread.getName());
        //获取线程名字
        String n1 = t1.getName();
        System.out.println(n1);
        //修改线程名字
        t1.setName("tttt");
        System.out.println(t1.getName());
        //创建第二个多线程对象
        MyThread2 t2 = new MyThread2();
        System.out.println(t2.getName());
        t2.setName("ssss");
        System.out.println(t2.getName());
        t2.start();
        //启动线程
        t1.start();
    }
}
class MyThread2 extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            //当前线程对象
            Thread currentThread = Thread.currentThread();
            System.out.println(currentThread().getName() + "-->" + i);
        }
    }
}


运行结果:


0a2653c851af460fa595bd959398a8f1.png


三、线程的sleep方法


关于线程的sleep方法:


static void sleep(long millis)


1、静态方法:Thread.sleep(1000);

2、参数是毫秒

3、作用:让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其它线程使用。


这行代码出现在A线程中,A线程就会进入休眠。

这行代码出现在B线程中,B线程就会进入休眠。

4、Thread.sleep()方法,可以做到这种效果:


间隔特定的时间,去执行一段特定的代码,每隔多久执行一次。


示例代码02:


public class ThreadTest06 {
    public static void main(String[] args) {
        //sleep方法让当前线程休眠指定时间,此处休眠5秒
        /*try {
        // 让当前线程进入休眠,睡眠5秒
        // 当前线程是主线程!!!
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("HelloWorld!");*/
        //此处每循环一次,就休眠一秒
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


运行结果:


2d65d23f6d4748949b924e4057485923.png


四、sleep方法的面试题


分支线程调用sleep方法,会休眠分支线程吗?


示例代码03:


public class ThreadTest07 {
    public static void main(String[] args) {
        //多态
        Thread t= new MyThread3();
        //修改名字
        t.setName("t");
        //启动分支线程
        t.start();
        try {
            // 问题:这行代码会让线程t进入休眠状态吗?
            // 在执行的时候还是会转换成:Thread.sleep(1000 * 5);
            // 这行代码的作用是:让当前线程进入休眠,也就是说main线程进入休眠。
            // 这样代码出现在main方法中,main线程睡眠。
            t.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("HeloWorld!");
    }
}
class MyThread3 extends Thread{
    public void run(){
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:


6de278e6d6694ce5bb08e7e842b7e74b.png


五、终止线程的休眠


sleep睡眠太久了,如果希望半道上醒来,你应该怎么办?也就是说怎么叫醒一个正在睡眠的线程??


注意:这个不是终断线程的执行,是终止线程的睡眠。


调用interrupt方法终止休眠的线程


示例代码04:


public class ThreadTest08 {
    public static void main(String[] args) {
        //创建线程接口实现类对象
        Thread t = new Thread(new MyRunnable2());
        t.setName("t");
        t.start();
        // 希望5秒之后,t线程醒来(5秒之后主线程手里的活儿干完了。)
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 终断t线程的睡眠(这种终断睡眠的方式依靠了java的异常处理机制。)
        t.interrupt();// 干扰,一盆冷水过去!
    }
}
class MyRunnable2 implements Runnable{
    // 重点:run()当中的异常不能throws,只能try catch
    // 因为run()方法在父类中没有抛出任何异常,子类不能比父类抛出更多的异常。
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "---> begin");
        try {
            // 睡眠1年
            Thread.sleep(1000 * 60 * 60 * 24 * 365);
        } catch (InterruptedException e) {
            // 打印异常信息
            //e.printStackTrace();
//            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "---> end");
        // 调用doOther
        //doOther();
    }
    // 其它方法可以throws
    /*public void doOther() throws Exception{
    }*/
}


运行结果:


8ec4f2997fb246878c34ecd6d122b7c6.png


六、强行终止线程的执行


调用现成的stop方法(此方法已过时)


在java中怎么强行终止一个线程的执行。

这种方式存在很大的缺点:容易丢失数据。因为这种方式是直接将线程杀死了,

线程没有保存的数据将会丢失。不建议使用。


示例代码05:


public class ThreadTest09 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable3());//出错点,看清构造器中的实现类,别写错
        t.setName("t");
        t.start();
        //模拟5秒,设置5秒终止
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //强制终止线程t//5秒后强制终止线程
        t.stop();//已过时
    }
}
class MyRunnable3 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
            //休眠一秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


运行结果:


12c3b7f3f8814309a195c64f051d4445.png


七、合理的终止一个线程的方法


使用if()循环的Return方法合理终止一个线程


示例代码06:


public class ThreadTest10 {
    public static void main(String[] args) {
        MyRunnable4 m = new MyRunnable4();
        Thread t = new Thread(m);
        t.setName("t");
        t.start();
        //模拟5秒
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //当5秒后把线程休眠标记设置为false,线程终止,不会导致数据丢失
        m.run = false;
    }
}
class MyRunnable4 implements Runnable{
    //定义线程休眠标记
    boolean run = true;
    @Override
    public void run() {
       for(int i=0;i<10;i++){
           if(run){
               System.out.println(Thread.currentThread().getName() + "--->" + i);
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }else{
               // return就结束了,你在结束之前还有什么没保存的。
               // 在这里可以保存呀。
               //save....
               //终止当前线程
               return;
           }
       }
    }


运行结果:


34e8d716411043c08c7ffba9fbba23de.png


八、线程调度概述


常见的线程调度模型有哪些?


1、抢占式调度模型:


那个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些。

java采用的就是抢占式调度模型。

2、均分式调度模型:


平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样。

平均分配,一切平等。

有一些编程语言,线程调度模型采用的是这种方式。

3、线程调度的方法


实例方法:


void setPriority(int newPriority) 设置线程的优先级

int getPriority() 获取线程优先级

最低优先级1

默认优先级是5

最高优先级10

优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)


示例代码07:


public class ThreadTest11 {
    public static void main(String[] args) {
        System.out.println("线程的最高优先级:" + Thread.MAX_PRIORITY);
        System.out.println("线程的最低优先级:" + Thread.MIN_PRIORITY);
        System.out.println("线程的默认优先级:" + Thread.NORM_PRIORITY);
        Thread.currentThread().setPriority(1);
        System.out.println(Thread.currentThread().getPriority());
        // main线程的默认优先级是:5
        //System.out.println(currentThread.getName() + "线程的默认优先级是:" + currentThread.getPriority());
        Thread t = new Thread(new MyRunnable5());
        t.setPriority(10);
        t.setName("t");
        t.start();
        // 优先级较高的,只是抢到的CPU时间片相对多一些。
        // 大概率方向更偏向于优先级比较高的。
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}
class MyRunnable5 implements Runnable{
    public void run(){
        // 获取线程优先级
        //System.out.println(Thread.currentThread().getName() + "线程的默认优先级:" + Thread.currentThread().getPriority());
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:


92ba0822ed0b46e1ae72df8a17d3a45b.png


九、线程让位


让位,当前线程暂停,回到就绪状态,让给其它线程。


静态方法:


static void yield() 让位方法

暂停当前正在执行的线程对象,并执行其他线程

yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用。

yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。

注意:在回到就绪之后,有可能还会再次抢到。


示例代码08:


public class ThreadTest12 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable6());
        t.setName("t");
        t.start();
        for(int i=1;i<1000;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}
class MyRunnable6 implements Runnable{
    @Override
    public void run() {
        for(int i=1;i<1000;i++){
            //每100个让位一次。
            if(i % 100 == 0){
                Thread.yield();// 当前线程暂停一下,让给主线程。v
            }
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:


d79b274929334152a6d38be91e2d1be3.png


十、线程合并


实例方法:void join()


示例代码09:


public class ThreadTest13 {
    public static void main(String[] args) {
        System.out.println("main ---> begin!");
        Thread t = new Thread(new MyRunnable7());
        t.setName("t");
        t.start();
        //合并线程
        try {
            t.join();//t合并到当前线程中,当前线程受阻塞,t线程执行直到结束
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main ---> over");
    }
}
class MyRunnable7 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<1000;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:

dfc80ca9d8004e6c9ddc00e8448ffc6a.png

相关文章
|
20小时前
|
Java
Java 与垃圾回收有关的方法
Java 与垃圾回收有关的方法
|
23小时前
|
缓存 Java
【Java基础】简说多线程(上)
【Java基础】简说多线程(上)
5 0
|
1天前
|
Java API 调度
[AIGC] 深入理解Java并发编程:从入门到进阶
[AIGC] 深入理解Java并发编程:从入门到进阶
|
1天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
1天前
|
安全 Java 编译器
是时候来唠一唠synchronized关键字了,Java多线程的必问考点!
本文简要介绍了Java中的`synchronized`关键字,它是用于保证多线程环境下的同步,解决原子性、可见性和顺序性问题。从JDK1.6开始,synchronized进行了优化,性能得到提升,现在仍可在项目中使用。synchronized有三种用法:修饰实例方法、静态方法和代码块。文章还讨论了synchronized修饰代码块的锁对象、静态与非静态方法调用的互斥性,以及构造方法不能被同步修饰。此外,通过反汇编展示了`synchronized`在方法和代码块上的底层实现,涉及ObjectMonitor和monitorenter/monitorexit指令。
6 0
|
1天前
|
监控 安全 Java
在Java中如何优雅的停止一个线程?可别再用Thread.stop()了!
在Java中如何优雅的停止一个线程?可别再用Thread.stop()了!
7 2
|
1天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
8 1
|
1天前
|
安全 Java
Java基础教程(15)-多线程基础
【4月更文挑战第15天】Java内置多线程支持,通过Thread类或Runnable接口实现。线程状态包括New、Runnable、Blocked、Waiting、Timed Waiting和Terminated。启动线程调用start(),中断线程用interrupt(),同步用synchronized关键字。线程安全包如java.util.concurrent提供并发集合和原子操作。线程池如ExecutorService简化任务管理,Callable接口允许返回值,Future配合获取异步结果。Java 8引入CompletableFuture支持回调。
|
1天前
|
存储 Java 测试技术
一文搞清楚Java中的方法、常量、变量、参数
在JVM的运转中,承载的是数据,而数据的一种变现形式就是“量”,量分为:**常量与变量**,我们在数学和物理学中已经接触过变量的概念了,在Java中的变量就是在程序运行过程中可以改变其值的量。
3 0
|
2天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
16 0