目录
Thread类是JVM用来管理线程的一个类,换句话说,每个线程都有一个唯一的Threadd对象与之关联。
1.Thread的常见的构造方法
方法 | 说明 |
---|---|
Thread() | 创建线程对象 |
Thread(Runnable target) | 使用Runnable对象创建线程对象 |
Thread(String name) | 创建线程对象,并命名 |
Thread(Runnable target ,String name) | 使用Runnable对象创建线程对象并命名 |
【了解】Thread(ThreadGroup group,Runnable target) | 线程可以被用来分组管理,分好的组即为目前我们了解即可。 |
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");
2.Thread的几个常见属性
属性 | 获取方法 |
---|---|
ID | getID() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
- ID是线程的唯一标识,不同线程不会重复。
- 名称是各种调试工具用到
- 状态表示线程当前所处的一个情况。
- 优先级高的线程理论上来说更容易被调度到。
- 关于后台线程,JVM会在一个线程的所有非后台线程结束后,才会结束运行。
- 是否存活,为run方法是否运行结束了
public class ThreadDemo {
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() + ": 我即将死去")
});
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());
}
}
3.启动一个线程 - start()
- 覆写run方法是提供给线程要做的事情的指令清单
- 线程对象可以认为是把 李四、王五叫过来了
- 而调用start()方法,线程才真正独立去执行
调用start方法,才真的在操作系统的底层创建出一个线程
4.中断一个线程
目前常见的有以下两种方式:
1.通过共享的标记来进行沟通
2.调用interrupt()方法来通知
示例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;
}
}
示例2-使用Thread》interruprted() 或者 Thread.currentThread().isInterruped() 代替自定义标志位。
Thread内部包含了一个Boolean类型的变量作为线程是否被中断的标记。
使用thread对象的interrupted()方法通知线程结束
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收到通知的方式有两种:
1.如果线程因为调用wait/join/sleep等方法而阻塞挂起,则以interruptedException异常的形式通知,清楚中断标志
当出现interruptedException的时候,要不要结束线程取决于catch中的代码的写法,可以选择忽略这个异常,也可以跳出循环结束的过程。
2.否则,知识内部的一个中断标志被设置,thread也可以通过
Thread.currentThread().isInterrupted()判断线程的中断标志被设置,不清楚中断标志这种方式通知收到的更及时,即使线程正在sleep也可以马上收到。
5.等待一个进程 - join()
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("王五⼯作结束了");
}
}
方法 | 说明 |
---|---|
public void join() | 等待线程结束 |
public void join (long millis) | 等待线程结束,最多等待millis毫秒 |
public void join (long millis,int nanos) | 同理,但可以更高精度 |
6.获取当前线程引用
方法 | 说明 |
---|---|
public static Thread currentThread(); | 返回当前线程对象的引用 |
public class ThreadDemo {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
}
}
7.休眠当前线程
这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的
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());
}
}