文章目录
-
- [1. Thread类的创建](#1. Thread类的创建)
-
- [1.1 自己创建类继承Thread类](#1.1 自己创建类继承Thread类)
- [1.2 实现Runnable接口](#1.2 实现Runnable接口)
- [1.3 使用匿名内部类创建Thread子类对象](#1.3 使用匿名内部类创建Thread子类对象)
- [1.4 使用匿名内部类创建Runnable子类对象](#1.4 使用匿名内部类创建Runnable子类对象)
- [1.5 使用lambda创建](#1.5 使用lambda创建)
- [2. Thread常见的构造方法](#2. Thread常见的构造方法)
-
- [2.1 Thread()](#2.1 Thread())
- [2.2 Thread(Runnable target)](#2.2 Thread(Runnable target))
- [2.3 Thread(String name)](#2.3 Thread(String name))
- [2.4 Thread(Runnable target, String name)](#2.4 Thread(Runnable target, String name))
- [3. Thread常见的属性](#3. Thread常见的属性)
- [4. 线程的使用](#4. 线程的使用)
-
- [4.1 启动线程](#4.1 启动线程)
- [4.2 中断线程](#4.2 中断线程)
- [4.3 等待线程](#4.3 等待线程)
- [4.4 休眠线程](#4.4 休眠线程)
1. Thread类的创建
1.1 自己创建类继承Thread类
java
package Thread;
//继承Thread类实现线程
class MyThread extends Thread{
@Override
public void run() {
System.out.println("hello run");
}
}
public class Dome1 {
public static void main(String[] args){
//创建线程
MyThread myThread = new MyThread();
//启动线程
myThread.start();
}
}
1.2 实现Runnable接口
java
//使用Runnable的方式创建线程
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("hello run");
}
}
public class Dome2 {
public static void main(String[] args){
//创建线程
MyRunnable myRunnable = new MyRunnable();
Thread t = new Thread(myRunnable);
//启动
t.start();
}
}
1.3 使用匿名内部类创建Thread子类对象
java
//通过匿名内部类的方式创建线程
public class Dome3 {
public static void main(String[] args) {
//创建线程
Thread t = new Thread(){
@Override
public void run() {
System.out.println("hello run");
}
};
//启动线程
t.start();
}
}
1.4 使用匿名内部类创建Runnable子类对象
java
//使用匿名内部类创建Runnable子类对象
public class Dome4 {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello run");
}
});
t.start();
}
1.5 使用lambda创建
java
//lambda实现线程
public class Dome5 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread( () -> {
System.out.println("hello run");
});
t.start();
}
}
2. Thread常见的构造方法
2.1 Thread()
java
//创建Thread对象
Thread t = new Thread();
2.2 Thread(Runnable target)
java
//使用Runnable对象创建线程对象
Thread t = new Thread(new Runnable);
2.3 Thread(String name)
java
//为这个线程命名
Thread t = new Thread("名字");
2.4 Thread(Runnable target, String name)
java
//使用Runnable对象创建线程对象并命名
Thraed t = new Thread(new Runnable,"名字");
3. Thread常见的属性
属性 | 获取方法 |
---|---|
ID | getId() |
name | getName() |
状态 | getState() |
优先级 | getPriority() |
是否为后台线程 | isDaemon() |
是否存活 | isAlive() |
是否中断 | isInterrupted() |
java
public class Test4 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
//Thread.currentThread调用当前线程对象,相当于t,这个时候t还未初始化成功,不能直接使用
System.out.println("ID: " + Thread.currentThread().getId());
System.out.println("name: " + Thread.currentThread().getName());
System.out.println("状态: " + Thread.currentThread().getState());
System.out.println("优先级: " + Thread.currentThread().getPriority());
System.out.println("是否为后台线程: " + Thread.currentThread().isDaemon());
System.out.println("是否存活: " + Thread.currentThread().isAlive());
System.out.println("是否中断: " + Thread.currentThread().isInterrupted());
});
t.start();
}
}
注意:
- ID 是线程的唯一标识,不同线程不会重复
- 名称是各种调试工具用到
- 状态表示线程当前所处的一个情况,下面我们会进一步说明
- 优先级高的线程理论上来说更容易被调度到
- 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
- 是否存活,即简单的理解,为 run 方法是否运行结束了
4. 线程的使用
4.1 启动线程
前面我们已经知道了线程的创建,构造等方法,但这些其实都是准备工作,还没有真正的从底层创建出一个线程,只有调用start方法够才算真正的创建成功线程。
//直接调用就可以 t.start()
4.2 中断线程
当线程启动的时候,有时里面是循环,这时线程便不会停止,我们便要想办法中断线程。中断线程有个简单的方法直接使用Thread.stop()方法,但是,这种方法是unsafe,而且基本上已经deprecated。
所以我们调用interrupt()方法进行停止线程,但它并不会直接停止线程,而是对线程内进行标记,标记为Boolean类的true。这个时候我们再调用下面两个方法。
public static boolean interruputed();
测试线程是否为中断状态,还执行后会标记清除为false。
public boolean isInterputed();
测试线程是否为中断状态,但不清除标记。
添加标志符进行中断:
java
//中断线程,添加标志位
public class Test3 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
//
while(!Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// e.printStackTrace();
break;
}
}
});
//启动线程
t1.start();
//休眠3秒
Thread.sleep(3000);
t1.interrupt();
}
}
注意:
如果休眠中中断线程,则会异常,反之,也是。
java
//中断线程,添加标志位
public class Test3 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
// while(!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("异常!");
}
// }
System.out.println("end!");
});
t1.start();
Thread.sleep(3000);
t1.interrupt();
System.out.println(t1.isInterrupted());
System.out.println(Thread.interrupted());
}
}
4.3 等待线程
方法 | 说明 |
---|---|
join() | 等待线程结束 |
join(long millis) | 等待线程结束,最多等待millis毫秒 |
join(long millis,int nanos) | 和2相比更加的精确 |
当我们同时启动几个线程,由于线程启动时随机无序的,我们无法得知谁先结束,这个时候就可以使用join方法让线程等待。
例如:当我们想让张三先上班,等张三上班结束,李四接班,那么我们就可以写出下面代码。
java
public class Test5 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName() + "在上班");
try {
Thread.sleep(1000);
} catch (InterruptedException e ){
break;
}
}
},"张三");
Thread t2 = new Thread(() -> {
while(!Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName() + "在上班");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
},"李四");
System.out.println("监督张三");
t1.start();
Thread.sleep(3000);
t1.interrupt();
t1.join();
System.out.println("监督李四");
t2.start();
Thread.sleep(3000);
t2.interrupt();
t2.join();
}
}
4.4 休眠线程
线程在执行的时候是非常快的,这个时候我们就可以让线程执行一次后就休眠一定时间,便于更好的观察。
上面代码中我们也多次用到。
java
Thread.sleep(long millis),里面millis单位是毫秒。