Java--多线程之join,yield,sleep;线程优先级;定时器;守护线程
Posted MinggeQingchun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
以上是关于Java--多线程之join,yield,sleep;线程优先级;定时器;守护线程的主要内容,如果未能解决你的问题,请参考以下文章
Java多线程之sleep,wait,join和yield关键字,以及线程的关闭
Java多线程系列---“基础篇”14之 wait,sleep,join,yield,park,unpark,notify等通信机制对比
java多线程sleep()yield()wait()join()的区别
Java并发之wait notify yield sleep join
Java多线程学习笔记— “Thread类三个方法:线程休眠sleep()线程礼让yield()线程强制执行join()”