Java中Thread类及常见方法
Posted 木木林Violet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中Thread类及常见方法相关的知识,希望对你有一定的参考价值。
Java中Thread类及常见方法
Thread类时JVM中用来管理线程的一个类,也就是指每个线程都有一个唯一的Thread对象与之对应和关联。
Thread类的对象是用来描述一个线程执行流的,JVM会将这些Thread对象组织起来,用于线程的管理和调度。
1. Thread的常见构造方法
2. Thread的常见属性
- ID是线程的唯一标识,不同的线程ID不会重复,并且不一定是从1开始分配ID。
- 名称是线程的名字,一般用在调试时,并且可以更改,且可重复。
- 状态表示线程当前所处的的一个情况。
- 优先级高度额线程理论上来说更容易被调度到(要看实际的线程调度策略)。
- 有关于后台线程,需要知道:JVM会在一个线程的所有非后台线程结束后,才会结束运行。
- 是否存活,也就是指线程 的run方法是否运行结束。
- 线程的中断回合线程的状态有一定的关系,一般是指线程在运行时,是否会被暂停运行。可自行设置,但对于JVM而言,仅仅为建议,具体情况还是得看JVM。
3. 启动线程
在之前的代码中,我们已经可以通过覆写run方法来创建一个线程,但线程对象被创建出来并不意味这线程就开始运行了。
因为我们覆写的run方法,只是告诉线程要做的事情的指令清单,但使用start方法,线程才会真正地去独立执行。
调用start方法,才真的在操作系统的底层创建出了一个线程。
4. 中断线程
在实际的执行流中,一个线程不一定会完全一直执行已经规定好了的步骤,可能在中途会有一些特殊的要求,于是需要增加一些机制,让线程暂时停止,先去干其他的事情,等其他的事情干完之后,再去接着做之前还未做完的事情。
目前常见的中断线程的方法有两种:
- 通过共享的标记来进行沟通。
- 调用interrupt方法来通知。
4.1. 通过共享的标记来进行沟通
需要非标志为加上volatile关键字。
public class ThreadDemo
private static class MyRunnable implements Runnable
public volatile boolean isQuit = false;
@Override
public void run()
while (!isQuit)
System.out.println(Thread.currentThread().getName() + ": 别管我,我忙着转账呢!");
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + ": 啊!险些误了大事");
public static void main(String[] args) throws InterruptedException
MyRunnable target = new MyRunnable();
Thread thread = new Thread(target, "李四");
System.out.println(Thread.currentThread().getName() + ": 让李四开始转账。");
thread.start();
Thread.sleep(10 * 1000);
System.out.println(Thread.currentThread().getName() + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
target.isQuit = true;
4.2. 调用interrupt方法来通知
interrupt可以让需要停止的线程看到停止信号后,可以主动把手上的工作做到一个阶段完成,然后再主动退出。
但实际上interrupt仅仅是发了个消息(给需要停止的线程设置了一个停止标志),实际上并不会影响线程的运行。
但若线程处于休眠状态时(比如sleep、join),意味着线程无法立即执行停止操作,则需要JVM以异常的形式,来通知线程。
public class ThreadDemo
private static class MyRunnable implements Runnable
@Override
public void run()
// 两种方法均可以
while (!Thread.interrupted())
//while (!Thread.currentThread().isInterrupted())
System.out.println(Thread.currentThread().getName() + ": 别管我,我忙着转账呢!");
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + ": 有内鬼,终止交易!");
// 注意此处的 break
break;
System.out.println(Thread.currentThread().getName() + ": 啊!险些误了大事");
public static void main(String[] args) throws InterruptedException
MyRunnable target = new MyRunnable();
Thread thread = new Thread(target, "李四");
System.out.println(Thread.currentThread().getName() + ": 让李四开始转账。");
thread.start(); Thread.sleep(10 * 1000);
System.out.println(Thread.currentThread().getName() + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
thread.interrupt();
thread对象收到通知的方式有两种:
- 如果线程是因为调用 wait / join / sleep 等方法二阻塞挂起,则会以 InterruptedException 异常的形式通知,并且清除中断标志。
- 否则就只是内部的一个中断标志被设置,thread对象可以通过,可以通过 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 来判断线程的中断标志是否被设置。这种方式的通知会更加及时,即使线程正在sleep状态也可以马上收到。
5. 等待线程
在例如使用IO时,我们会需要等待线程完成它的工作后,才能进行值的下一步的工作于是会使用到线程的等待。
public class ThreadDemo
public static void main(String[] args) throws InterruptedException
Runnable target = () ->
for (int i = 0; i < 10; i++)
try
System.out.println(Thread.currentThread().getName() + ": 我还在工作!");
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + ": 我结束了!");
;
Thread thread1 = new Thread(target, "李四");
Thread thread2 = new Thread(target, "王五");
System.out.println("先让李四开始工作");
thread1.start();
thread1.join();
System.out.println("李四工作结束了,让王五开始工作");
thread2.start();
thread2.join();
System.out.println("王五工作结束了");
6. 获取线程引用
public class ThreadDemo
public static void main(String[] args)
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
7. 休眠线程
虽然我们可以使用sleep来控制线程休眠,但因为线程的调度是不可控的,所以这个方法只能保证实际休眠时间大于等于参数设置的休眠时间。
public class ThreadDemo
public static void main(String[] args) throws InterruptedException
System.out.println(System.currentTimeMillis());
Thread.sleep(3 * 1000);
System.out.println(System.currentTimeMillis());
8. 线程让出资源
Thread类中的yield方法,可以让出一部分资源,其中主要指CPU资源,让线程从运行状态,转换为就绪状态,并且随时可以继续被调度回CPU。
yield方法主要用于执行一些耗时较长的计算任务时,为了防止计算机处于“卡顿”的线程,会时不时的让出一些CPU的资源,给操作系统内的其他进程使用。
表现为CPU主要由其他线程使用,而使用yield的线程使用CPU的机会会很少。
以上是关于Java中Thread类及常见方法的主要内容,如果未能解决你的问题,请参考以下文章