常用属性
四个获取
- getId 获取id
- getName 获取线程名字
- getState 获取状态
- getPriority 获取优先级
三个判断
- isAlive 判断是否存活
- isInterrupted 判断是否被打断
- isDaemon 判断是否存在后台线程
判断是否存活,简单理解就是run是否结束了。
判断是否被打断
判断是否存在后台线程,JVM会在一个进程的所有非后台线程都结束后,才会结束运行
线程属性的使用
public class JAVA_Thread03 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
System.out.println(Thread.currentThread().getName() + ": 我还 活着");
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ": 我即将死去");
},"我叫坤kun");
System.out.println(Thread.currentThread().getName()
+ ": ID: " + thread.getId());
System.out.println(Thread.currentThread().getName()
+ ": 名称: " + thread.getName());
System.out.println(Thread.currentThread().getName()
+ ": 状态: " + thread.getState());
System.out.println(Thread.currentThread().getName()
+ ": 优先级: " + thread.getPriority());
System.out.println(Thread.currentThread().getName()
+ ": 后台线程: " + thread.isDaemon());
System.out.println(Thread.currentThread().getName()
+ ": 活着: " + thread.isAlive());
System.out.println(Thread.currentThread().getName()
+ ": 被中断: " + thread.isInterrupted());
thread.start();
while (thread.isAlive()) {}
System.out.println(Thread.currentThread().getName()
+ ": 状态: " + thread.getState());
}
}
常见方法
构造 + 启 断 等 获 眠
构造方法
在上一个文章已经比较详细地介绍过了,这里就不加赘述。感兴趣地小伙伴可以去看看。
启动 start()
用一个形象的例子来形容就是:
创建线程—叫来一个打工人,重写run方法—告诉打工人应该做什么,启动start()—告诉打工人开工了。
中断
1.使用自定义标记控制中断
volatile关键字修饰的Boolean可以在Runnable和main沟通
关键点
1.写一个MyRunnable类实现Runnable接口,在类中定义一个使用volatile修饰的boolean变量,初始化为false;
2.实例化这个类,才会出现volatile关键字修饰的标记
3.在需要中断的时候,调用实例化的MyRunnable类的volatile修饰的变量,修改为true。
public static class MyRunnable implements Runnable {
public volatile boolean isStop=false;
public void run(){
while(!isStop){
System.out.println(Thread.currentThread().getName() + "正在转钱");
try{
sleep(10*100);
}catch(InterruptedException e){
}
}
System.out.println("有内鬼,终止交易!");
System.out.println(Thread.currentThread().getName()+"停止转钱");
}
}
public static void main(String[] args) {
MyRunnable myRunnable=new MyRunnable();
Thread thread = new Thread(myRunnable, "坤坤");
System.out.println("开始转钱");
thread.start();
try{
sleep(10*1000);
}catch(InterruptedException e){
}
System.out.println("老板发现有内鬼,停止交易!");
myRunnable.isStop=true;
}
2.使用Thread.interrupted()或者Thread.currentThread.isInterrupted()方法代替自定义标记位
Thread类内部自带返回类型是boolean的变量作为是否被interrupt的标记
方法名 | 方法介绍 |
---|---|
public void interrupt() | 中断的执行方法,用来中断对象相关联的线程,线程如果堵塞则通过异常通知,否则设定标记位 |
public boolean interrupted() | 判断是否设置中断标记位,调用销毁标记位 |
public boolean isInterrupeted() | 判断是否设置中断标记位,调用不销毁标记位 |
public static class MyRunnable implements Runnable {
public void run(){
while(!Thread.interrupted()){
System.out.println(Thread.currentThread().getName() + "正在转钱");
try{
sleep(10*100);
}catch(InterruptedException e){
System.out.println("有内鬼,终止交易!");
break;
}
}
System.out.println(Thread.currentThread().getName()+"停止转钱");
}
}
public static void main(String[] args) {
// MyRunnable myRunnable=new MyRunnable();
Thread thread = new Thread(new MyRunnable(), "坤坤");
System.out.println("开始转钱");
thread.start();
try{
sleep(10*1000);
}catch(InterruptedException e){
}
System.out.println("老板发现有内鬼,停止交易!");
thread.interrupt();
}
这里与使用标记点由三个不同点
Thread收到通知的方式有两种
1.线程因为调用wait/join/sleep等方法而阻塞挂起,会通过InterruptException异常通知,并消除中断标志。
2.如果没有阻塞挂起,可以通过以下方式判断中断标志是否被设置。
boolean interrupted(),使用后会清除中断标志
boolean isInterrupted(),使用后不会清除标志,效率更高更及时,即使线程是在sleep也可以收到。
等待 — join()
等待的使用其实在前面证明并发和串行的运行效率的时候就已经使用过了。join()的使用一般是需要其他线程等待当前调用了join()方法的线程结束之后才能进行。
个人理解为:等我。一个线程调用了join()方法,可以看成他跟其他没有调用join()方法的线程说:"等我."然后其他线程等待他运行结束才开始运行。
基本使用如下:
public static void main(String[] args) throws InterruptedException {
Runnable target = () -> {
for (int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName()
+ ": 我还在唱!");
Thread.sleep(100);
} 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();
// Thread.currentThread().join();
thread1.join();
System.out.println("坤坤工作结束了,让甜甜圈开始工作");
thread2.start();
thread2.join();
System.out.println("甜甜圈工作结束了");
}
以下给出三个片段来证明
1.正常使用join()可以看见线程会很有秩序的按照顺序运行
2.只有后边使用join()方法等待
可以看到,线程二会和线程一抢着运行,因为线程一没有说"等我"(调用join()方法)
3.如果不小心对main线程使用了join(),那么恭喜你,出不来了
因为这里的线程二在等待主线程结束,然而如果主线程结束就都结束了,你也等不到线程二运行了。
– | – |
---|---|
join() | 不延迟 |
join(long millis) | 按毫秒延迟 |
join(long millis,int nanos | 按更精细化的纳秒延迟 |
获取 — currentThread()
就直接调用Thread使用currentThread()就可以了,没什么想说的。
Thread.currentThread();
休眠 — sleep()
使用sleep()
如果只有一个参数就是毫秒,
两个参数,前一个是毫秒,后一个是纳秒
thread.sleep();