文章目录
- 1. Thread类的创建
- 1.1 自己创建类继承Thread类
- 1.2 实现Runnable接口
- 1.3 使用匿名内部类创建Thread子类对象
- 1.4 使用匿名内部类创建Runnable子类对象
- 1.5 使用lambda创建
- 2. Thread常见的构造方法
- 2.1 Thread()
- 2.2 Thread(Runnable target)
- 2.3 Thread(String name)
- 2.4 Thread(Runnable target, String name)
- 3. Thread常见的属性
- 4. 线程的使用
- 4.1 启动线程
- 4.2 中断线程
- 4.3 等待线程
- 4.4 休眠线程
1. Thread类的创建
1.1 自己创建类继承Thread类
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接口
//使用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子类对象
//通过匿名内部类的方式创建线程
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子类对象
//使用匿名内部类创建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创建
//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()
//创建Thread对象
Thread t = new Thread();
2.2 Thread(Runnable target)
//使用Runnable对象创建线程对象
Thread t = new Thread(new Runnable);
2.3 Thread(String name)
//为这个线程命名
Thread t = new Thread("名字");
2.4 Thread(Runnable target, String name)
//使用Runnable对象创建线程对象并命名
Thraed t = new Thread(new Runnable,"名字");
3. Thread常见的属性
属性 | 获取方法 |
---|---|
ID | getId() |
name | getName() |
状态 | getState() |
优先级 | getPriority() |
是否为后台线程 | isDaemon() |
是否存活 | isAlive() |
是否中断 | isInterrupted() |
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();
测试线程是否为中断状态,但不清除标记。
添加标志符进行中断:
//中断线程,添加标志位
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();
}
}
注意:
如果休眠中中断线程,则会异常,反之,也是。
//中断线程,添加标志位
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方法让线程等待。
例如:当我们想让张三先上班,等张三上班结束,李四接班,那么我们就可以写出下面代码。
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 休眠线程
线程在执行的时候是非常快的,这个时候我们就可以让线程执行一次后就休眠一定时间,便于更好的观察。
上面代码中我们也多次用到。
Thread.sleep(long millis),里面millis单位是毫秒。