1.线程创建
这里介绍线程创建常用的五种方法
1.继承Thread,重写run
class MyThread extends Thread{public void run(){//这里写的代码就是线程要完成的任务while (true){System.out.println("hello thread");try {Thread.sleep(1000);//线程会休眠一秒再执行,不休眠会执行得很快} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}public class Demo1 {public static void main(String[] args) {Thread t=new MyThread();// 没有创建出新的线程, 就是在主线程中执行上述 run 中的循环打印.//t.start();//hello thread 和 hello main 并发执行t.run();//只有 hello threadwhile(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
start 和 run这两个方法的区别是什么呢?
作用功能不同:
- run方法的作用是描述线程具体要执行的任务;
- start方法的作用是真正的去申请系统线程
运行结果不同:
- run方法是一个类中的普通方法,主动调用和调用普通方法一样,会顺序执行一次;
- start调用方法后, start方法内部会调用Java 本地方法(封装了对系统底层的调用)真正的启动线程,并执行run方法中的代码,run 方法执行完成后线程进入销毁阶段。
调用start方法: 调用run方法:
2.重写Runnable方法,重写run,把Runnable实例传入到Thread中
class MyRunnable implements Runnable{public void run(){while (true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}public class Demo2 {public static void main(String[] args) {Thread t=new Thread(new MyRunnable());t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
3.针对 1的变形,使用匿名内部类, 继承 Thread 并重写 run.
public class Demo3 {public static void main(String[] args) {Thread t=new Thread(){public void run(){while (true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
4.实现 Runnable, 重写 run, 使用匿名内部类
public class Demo4 {public static void main(String[] args) {Thread t=new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();while (true){System.out.println("hello main");try {Thread.sleep(10000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
5.使用 lambda 表达式
public class Demo5 {public static void main(String[] args) {Thread t=new Thread(() -> {while (true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
上述每种方法执行的结果都是大同小异,就是hello main和hello thread 并发执行,并且是抢占式执行,你也不知道hello thread 的下一句还是hello thread 或者是hello main。
2.线程中断
线程运行起来之后如果想要中断,就需要采用interrupt()方法来中断
public static void main(String[] args) {Thread t = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {break;}}});t.start();try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}t.interrupt();}
3.线程等待
有时,我们需要等待⼀个线程完成它的⼯作后,才能进行自己的下⼀步⼯作。
public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true){System.out.println("1");}}});t.start();while(true){System.out.println("2");}}
由于上述代码中main 和 t线程 之间的结束顺序是不确定的,如果希望让代码里面的 t能够先结束main 后结束,就可以在 main 中使用线程等待(join)
这个方法有三种,每种功能不一样
方法 | 说明 |
public void join() | 等待线程结束(死等) |
public void join(long millis) | 等待线程结束,最多等 millis 毫秒 |
public void join(long millis, int nanos) | 同理,但可以更高精度 |
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true){System.out.println("1");}}});t.start();t.join();while(true){System.out.println("2");}}
main 中线程调用 t.join 就是让 main 线程被阻塞并等待t线程.
由于这个代码调用的是死等的那个join方法,就会导致main线程陷入无尽等待一直无法执行,只有t线程执行,结果就是一直只有1。
如果用其余两个方法,那么结果就是main线程会先等待t线程执行一段时间后再开始执行。
4.线程休眠
方法 | 说明 |
public static void sleep(long millis) throws InterruptedException | 让当前线程休眠一定时间 |
public static void sleep(long millis, int nanos) throws InterruptedException | 让线程休眠一定时间(时间精度更高) |
前面的代码执行的时候我们会发现线程执行的速度很快,让线程休眠可以更好地看到线程执行的过程。
public static void main(String[] args) throws InterruptedException {Thread t=new Thread(()->{while (true){System.out.println("tjc");try {Thread.sleep(2000);//t线程会休眠两秒再执行} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();while (true){System.out.println("hs");Thread.sleep(2000);//main线程会休眠两秒执行}
}
5.获取线程实例
方法 | 说明 |
public static Thread currentThread(); | 返回当前线程对象的引用 |
public static void main(String[] args) {Thread thread = Thread.currentThread();System.out.println(thread.getName());}
得到的是main线程的实例