毕业设计做购物网站的要求,调查问卷wordpress,专业的网站建设宝安西乡,东莞房产网站建设目录
一、Thread 的常⻅构造⽅法
继承Thread代码#xff1a;
实现Runnable接口代码: 二、Thread 的⼏个常⻅属性
1、id#xff1a;
2、获取线程的名字。
3、进程的状态#xff1a;
4、在java中设置的优先级#xff0c;
5、是否后台线程#xff0c;
6、是否存活
实现Runnable接口代码: 二、Thread 的⼏个常⻅属性
1、id
2、获取线程的名字。
3、进程的状态
4、在java中设置的优先级
5、是否后台线程
6、是否存活
7、是否中断
8、等待线程结束
9、获取线程的引用currentThread() 一、Thread 的常⻅构造⽅法 最后一个线程组的概念是java的概念和系统中的线程组不一样不是同一个东西。
第一个和第二个构造方法在初阶一有介绍
链接多线程Thread初阶一认识线程-CSDN博客
第三是创建一个线程并且可以给这个线程命名并不是它默认的Thread-0 / 1 / 2.....第四个也是可以给线程对象命名不过是使用接口的方法。
继承Thread代码 class MyThread extends Thread {Overridepublic void run() {System.out.println(hello thread1);}String name;public MyThread(String name) {super(name);this.name name;}
}
public class ThreadDemo1 {public static void main(String[] args) {Thread t1 new MyThread(这是我的线程);t1.start();Thread t2 new Thread(这是我的线程){Overridepublic void run() {System.out.println(hello thread2);}};t2.start();}
}执行效果 两个线程 上面两种的两种创建线程方式都可以。 实现Runnable接口代码: class MyThread2 extends Thread {String name;public MyThread2(String name) {super(name);this.name name;}Overridepublic void run() {System.out.println(hello thread1);}
}
public class TestDemo2 {public static void main(String[] args) {Thread t1 new MyThread2(这是我的线程1);t1.start();Thread t2 new Thread(这是我的进程2) {Overridepublic void run() {System.out.println(hello thread2);}};t2.start();}
}执行效果 两个线程 注意我们创建的线程如果不起名字默认是Thread-0 1 2 3....给不同线程起不同名字对于线程的执行没啥影响主要是为了方便调试线程之间的名字是可以重复的在同一个工作中需要多个线程完成都可以起一样的名字但是名字也不要乱起最后要有一定的描述性。 二、Thread 的⼏个常⻅属性 1、id
jvm自动分配的身份标识会保证唯一性。
2、获取线程的名字。
3、进程的状态
就绪状态、阻塞状态线程也有状态Java中对线程的状态进行了进一步的区分比系统原生的状态更丰富一些。
4、在java中设置的优先级
效果不是很明显因为系统是随机调度的对内核的调度器调度过程会产生一些影响。
5、是否后台线程
也称为是否守护线程比较抽象所以记住和理解是否后台线程会轻松一些与此相反也有前台线程和Android上的前台app后台app完全不同。
后台线程和前台线程的区别前台线程的运行会阻止进程结束 后台线程的运行不会阻止进程结束 我们创建的线程默认是前台进程。 如下代码 public class TestDemo3 {public static void main(String[] args) {Thread t new Thread() {Overridepublic void run() {while (true) {System.out.println(hello thread);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};t.start();}
}执行效果会不停的输出打印hello thread 那我们试着把这个线程设置为后台线程试试默认为前台代码 public class TestDemo3 {public static void main(String[] args) {Thread t new Thread() {Overridepublic void run() {while (true) {System.out.println(hello thread);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};//在start之前设置线程为后台线程不能在start之后设置t.setDaemon(true);t.start();}
}执行效果 根本就没有打印hello thread进程就结束了因为是后台进程不会阻止进程的结束。 设为true是后台后台可以理解为背后不出面的人你感知不到后台不会阻止进程结束。 不设为true是前台前台可以理解为明面上的人你能感知到前台会阻止进程结束。 6、是否存活
isAlive( )表示内核中的线程PCB是否还存在。java代码中定义的线程对象Thread实现虽然是表示一个线程但这个对象本身的生命周期和内核中的PCB生命周期 是不完全一样的。 isAlive的测试代码 public class TestDemo4 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}});System.out.println(start之前 t.isAlive());t.start();System.out.println(start之后 t.isAlive());Thread.sleep(2000);System.out.println(t结束之后 t.isAlive());}
} 执行效果 解释启动线程之前也就是start之前t这个实例线程是还没开始的所以isAlive返回的是falsestart后就查看这个线程存不存在因为线程也刚启动所以isAlive返回的是true休眠两秒之后t线程已经跑完了所以isAlive返回的也是false。 7、是否中断
也是终止的意思。 下面写一个代码用boolean类型的变量来控制while循环也起到终止线程的作用。 public class ThreadDemo1 {private static boolean isQuit false;public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {while (!isQuit) {System.out.println(我是一个线程正在工作);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println(线程工作完毕);});t.start();Thread.sleep(3000);System.out.println(让线程结束);isQuit true;}
} 注意这里的isQuit变量放在类中不放在方法里作为局部变量的原因是涉及到了变量捕获如果放在main方法里是局部变量就必须要加 final 修饰将其变成常量为什么呢这时因为main线程和我们创建的线程的栈帧生命周期不同如果main线程先结束了我们创建的线程要获取这个变量但是我们main线程的栈帧生命周期已经结束了我们拿不到这个变量java这里的做法就比较暴力直接把这个变量变成常量要么这个变量就是全局变量以至于不会发生上面的情况。 执行效果 这时我们也可以使用jdk里自带的方法isInterrupted( ) 代码如下 public class ThreadDemo2 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {while (!Thread.currentThread().isInterrupted()) {System.out.println(我是一个线程正在工作);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(线程执行完毕);});t.start();Thread.sleep(3000);System.out.println(让线程结束);t.interrupt();}
} 执行效果 这个线程并不会结束会继续执行。 解释可以看到这里抛出了个异常而这个异常是InterruptedException 异常 如果没有sleepinterrupt是可以让线程顺利结束的但是有了sleep就会引起变数。 这说明sleep这出现问题了为什么呢原因是这个线程还在执行main线程休眠3秒后终止了这个线程但sleep还没休眠够1秒这里就会提前唤醒。 这里提前唤醒会做两件事 1、抛出 InterruptedException 紧接着就会被catch获取到。 2、清除 Thread 对象的 isInterrupt 标志位。sleep清空标志位是为了给程序猿更多的“可操作性空间”。 所以interrupt已经把标志位设置为true了sleep被提前唤醒清除了isInterrupt标志位后就又把标志位设回了false这个while循环还是能进去的所以线程还在继续执行。 此时程序猿就可以在catch语句中加入一些代码来做一些处理 1、让线程立即结束。加上break 2、让线程不结束继续执行。不加break 3、让线程执行一些逻辑后再结束。写一些其他代码再加break 对于一个服务器程序来说稳定性很重要这些所谓的“问题”在java中就会以异常的形式体现出来可以通过catch语句对这些异常进行处理。主要的几种处理方式 1、尝试自动恢复 2、记录日志 3、发出警报 8、等待线程结束
join 。我们知道多线程的执行顺序是不同的随机调度抢占式执行有不可预期性虽然线程的调度是无序的但是我们可以调用一些api来影响带线程的执行顺序join就是一种方式影响 线程结束 的先后顺序。比如t2 线程等待 t1这时一定是 t1先结束t2 后结束。这里的join就会使 t2 线程阻塞。 代码 public class ThreadDemo3 {public static void main(String[] args) {Thread t new Thread(() - {for (int i 0; i 5; i) {System.out.println(我是一个线程正在工作);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println(线程结束);});t.start();//t.join();System.out.println(这时一个主线程在t线程结束后再执行);}
}我们想让t线程执行完后再执行主线程如果不写join方法。因为多线程的调度是随机性的执行效果如下 执行效果和我们预期的不一样加上join方法后 代码 public class ThreadDemo3 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {for (int i 0; i 5; i) {System.out.println(我是一个线程正在工作);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}System.out.println(线程结束);});t.start();t.join();System.out.println(这时一个主线程在t线程结束后再执行);}
}执行效果 结果和我们想要预期效果相同。这里的join的意思是让 t 线程执行完再执行本线程。 这里是让main线程主动放弃去调度器调度t 线程执行完后main线程才执行这也代表哪个线程调用join哪个线程就是阻塞等待。这里就有了先后顺序。 注意这里的先后顺序和优先级不同优先级是系统调度器在内核中完成的工作即使优先级有差异但是每个线程的执行顺序还是随机的控制不了。 等待线程结束还有两个重载方法里面放的是要等待的时间,如图 如果join不加参数就是死等第一个加参数的就是等待多少毫秒第二个加参数数值精确到纳秒不过很少用因为计算机精确不到这么小。加参数是带有时间的等。 注意有时候不想等我们也可以不等例如加 interrupt可以终止这个等待我们也可以在idea看到join的实现是throws了 InterruptedException的。 9、获取线程的引用currentThread() 我们对于一个类继承Thread是可以通过this拿到线程的实例的 代码如下 class MyThread extends Thread {Overridepublic void run() {System.out.println(id: this.getId() name: this.getName());}
}
public class ThreadDemo1 {public static void main(String[] args) {Thread t new MyThread();t.start();}
} 效果如下 但是如果是接口或者我们使用匿名内部类 / lambda表达式就不能获取到Thread的引用了这时Thread已经给我们提供了方法获取引用了Thread.currentThread()。如下展示 代码 public class ThreadDemo2 {public static void main(String[] args) {Thread t1 new Thread(() - {Thread t Thread.currentThread();System.out.println(t.getId());});Thread t2 new Thread(() - {Thread t Thread.currentThread();System.out.println(t.getName());});t1.start();t2.start();}
} 效果如下 都看到这了点个赞再走吧谢谢谢谢谢