Java--多线程之join,yield,sleep;线程优先级;定时器;守护线程(三)

Java--多线程之并发,并行,进程,线程(一)_MinggeQingchun的博客-CSDN博客

Java--多线程之终止/中断线程(二)_MinggeQingchun的博客-CSDN博客_java中断线程

Java--多线程之synchronized和lock;死锁(四)_MinggeQingchun的博客-CSDN博客

Java--多线程之生产者消费者模式;线程池ExecutorService(五)_MinggeQingchun的博客-CSDN博客  

一、线程常用方法

/**
1、获取当前线程对象
    Thread t = Thread.currentThread();
2、获取线程对象的名字
    String name = 线程对象.getName();
3、修改线程对象的名字
    线程对象.setName("线程名字");
4、当线程没有设置名字的时候,默认的名字
    Thread-0
    Thread-1
    .....
 */
public class ThreadMethod {
    public static void main(String[] args) {
        //获取当前线程对象,currentThread()
        Thread t = Thread.currentThread();
 
        //获取线程名字"main",getName()
        System.out.println(t.getName());
 
        Thread t1 = new Thread();
        Thread t2 = new Thread();
        //线程默认名字:Thread-0;Thread-1
        System.out.println(t1.getName());//Thread-0
        System.out.println(t2.getName());//Thread-1
 
        //设置线程名字,setName()
        t1.setName("t1");
        System.out.println(t1.getName());//t1
    }
}

二、join

join()方法是Thread 类中的一个方法,它的作用是将当前线程挂起,等待其他线程结束后再执行当前线程,即当前线程等待另一个调用join()方法的线程执行结束后再往下执行

通常用于在main主线程内,等待其它调用join()方法的线程执行结束再继续执行main主线程

/**
 * void join()
 * 合并线程
 * */
public class ThreadJoin {
    public static void main(String[] args) {
        System.out.println("main begin");

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < 100; i++){
                    System.out.println(Thread.currentThread().getName() + "--->" + i);
                }
            }
        });
        t.setName("t");
        t.start();

        try {
            t.join();// 当前主线程进入阻塞,t线程执行,直到t线程结束;当前线程才可以继续执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("main over");
    }
}

三、yield

yield()方法的作用是放弃当前的cpu的资源,将他让给其他的任务去占用cpu执行时间。 但是放弃的时间不确定,有可能刚刚放弃又马上获得cpu时间片

yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

/**
 * static void yield()  让位方法
 * 静态方法:Thread.yield();
 *
 * 暂停当前正在执行的线程对象,并执行其他线程
 * yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用
 * yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”
 * 注:在回到就绪之后,有可能还会再次抢到
 * */
public class ThreadYeild {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1;i < 10000;i++){
                    System.out.println(Thread.currentThread().getName() + "---->" + i);

                    if (i % 100 == 0){
                        Thread.yield();
                    }
                }
            }
        });
        t.setName("t");
        t.start();

        for (int i = 1;i < 10000;i++){
            System.out.println(Thread.currentThread().getName() + "---->" + i);
        }
    }
}

四、sleep

线程sleep方法: static void sleep(long millis)

1、静态方法:Thread.sleep(1000);参数是毫秒

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

3、Thread.sleep()方法,可以做到间隔特定的时间,去执行一段特定的代码,每隔多久执行一次

/**
线程sleep方法:
    static void sleep(long millis)
    1、静态方法:Thread.sleep(1000);参数是毫秒
    2、作用:让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其它线程使用
    3、Thread.sleep()方法,可以做到间隔特定的时间,去执行一段特定的代码,每隔多久执行一次
 */
public class ThreadSleepTest {
    public static void main(String[] args) {

        //让当前主线程进入休眠,睡眠2秒
        try {
            Thread.sleep(1000 * 2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello world");

        for(int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);

            // 睡眠1秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < 10000; i++){
                    System.out.println(Thread.currentThread().getName() + "--->" + i);
                }
            }
        });
        t.start();

        try {
            /**
             * 这里虽然是分支线程 t 调用sleep()方法,但是在执行时还是会转换成:Thread.sleep(1000 * 5);
             * 因此会让当前主线程main进入休眠
             * */
            t.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Hello,我睡醒了");
    }
}

五、线程优先级

1、线程调度模型

(1)抢占式调度模型:

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

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

(2)均分式调度模型:

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

2、线程调度方法

实例方法:

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

最低优先级1;默认优先级是5;最高优先级10

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

/**
 * 线程优先级
 *
 * void setPriority(int newPriority)    设置线程的优先级
 * int getPriority()                    获取线程优先级
 *
 * 最低优先级1;默认优先级是5;最高优先级10
 *
 * */
public class ThreadPriority {
    public static void main(String[] args) {
        System.out.println("线程最高优先级:"+Thread.MAX_PRIORITY);//10
        System.out.println("线程最低优先级:"+Thread.MIN_PRIORITY);//1
        System.out.println("线程默认优先级:"+Thread.NORM_PRIORITY);//5

        //线程默认优先级
        System.out.println(Thread.currentThread().getName() + "线程的默认优先级是:" + Thread.currentThread().getPriority());

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < 10000; i++){
                    System.out.println(Thread.currentThread().getName() + "-->" + i);
                }
            }
        });
        t.setName("t");
        t.setPriority(10);
        t.start();

        Thread.currentThread().setPriority(1);

        // 优先级较高的,只是抢到的CPU时间片相对多一些。
        // 大概率方向更偏向于优先级比较高的。
        for(int i = 0; i < 10000; i++){
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}

六、timer定时器

Timer类和TimerTask类

Timer定时器主要用于做 定时任务 或者 按照一定的时间间隔做循环任务

java.util.Timer作为定时器,用于启动定时任务。

java.util.TimerTask实现了 Runnable 接口,需要重写**run()**方法,用于存放我们要做的任务

1、一个Timer定时器只会开启一个新线程

2、一个Timer定时器可以开启多个TimerTask定时任务,但这些任务只是在同一个线程下轮流执行的

/**
 使用定时器指定定时任务
 */
public class TimerTest {
    public static void main(String[] args) {
        Timer timer = new Timer();

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        df.format(date);

        //timer.schedule(定时任务, 第一次执行时间, 间隔多久执行一次);
        timer.schedule(new MyTimerTask(), date,1000);
    }
}

//定时任务类
class MyTimerTask extends TimerTask{

    @Override
    public void run() {
        //需要执行的任务
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        System.out.println(df.format(date) + "完成数据备份");
    }
}

七、守护线程

Java语言中线程分为两大类:

1、用户线程

2、守护线程(即 Daemon thread,后台线程)是个服务线程,用来服务于用户线程

其中具有代表性的就是:垃圾回收线程(守护线程)

守护线程的特点: 一般守护线程是一个死循环,所有的用户线程只要结束,守护线程自动结束

在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出

存在任意一个用户线程的时候,JVM就不会退出

JDK 官方文档中有如下一段话

The Java Virtual Machine exits when the only threads running are all daemon threads.

当 JVM 中不存在任何一个正在运行的非守护线程时,则 JVM 进程即会退出

注:

1、主线程main方法是一个用户线程

2、thread.setDaemon(true) 必须在 thread.start() 之前设置,否则会抛出 IllegalThreadStateException 异常

/**
 守护线程

 Java语言中线程分为两大类:
    一类是:用户线程
    一类是:守护线程(后台线程)
    其中具有代表性的就是:垃圾回收线程(守护线程)

 守护线程的特点:
    一般守护线程是一个死循环,所有的用户线程只要结束,守护线程自动结束

 注:主线程main方法是一个用户线程

 守护线程使用场景
    每天00:00的时候系统数据自动备份数据
 * */

public class DaemonThreadTest {
    public static void main(String[] args) {
        DamenThread t = new DamenThread();
        t.setName("t");

        // setDaemon(true)将t设置为守护线程
        t.setDaemon(true);

        t.start();

        for (int i = 1;i <= 10;i++ ){
            System.out.println(Thread.currentThread().getName() + "---->" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class DamenThread extends Thread{
    private int i = 1;

    @Override
    public void run() {
        // 死循环,但由于该线程是守护线程,当用户线程结束,守护线程自动终止
        while (true){
            System.out.println(Thread.currentThread().getName() + "---->" + (i++));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值