【大数据】学习笔记
文章目录
1 Java SE
第9章 多线程
9.3 Thread类
9.3.1 构造方法
- public Thread() :分配一个新的线程对象。
- public Thread(String name) :分配一个指定名字的新的线程对象。
- public Thread(Runnable target) :分配一个带有指定目标新的线程对象。
- public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。
9.3.2 常用方法系列1
-
public void run() :此线程要执行的任务在此处定义代码。
-
public String getName() :获取当前线程名称。
-
public static Thread currentThread() :返回对当前正在执行的线程对象的引用。
-
public final boolean isAlive():测试线程是否处于活动状态。如果线程已经启动且尚未终止,则为活动状态。
-
public final int getPriority() :返回线程优先级
-
public final void setPriority(int newPriority) :改变线程的优先级
- 每个线程都有一定的优先级,优先级高的线程将获得较多的执行机会。每个线程默认的优先级都与创建它的父线程具有相同的优先级。Thread类提供了setPriority(int newPriority)和getPriority()方法类设置和获取线程的优先级,其中setPriority方法需要一个整数,并且范围在[1,10]之间,通常推荐设置Thread类的三个优先级常量:
- MAX_PRIORITY(10):最高优先级
- MIN _PRIORITY (1):最低优先级
- NORM_PRIORITY (5):普通优先级,默认情况下main线程具有普通优先级。
public static void main(String[] args) {
Thread t = new Thread(){
public void run(){
System.out.println(getName() + "的优先级:" + getPriority());
}
};
t.setPriority(Thread.MAX_PRIORITY);
t.start();
System.out.println(Thread.currentThread().getName() +"的优先级:" + Thread.currentThread().getPriority());
}
9.3.3 常用方法系列2
-
public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
-
public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
-
public static void yield():yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,希望优先级与当前线程相同或更高的其他线程能够获得执行机会,但是这个不能保证,完全有可能的情况是,当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。
-
void join() :等待该线程终止。
void join(long millis) :等待该线程终止的时间最长为 millis 毫秒。如果millis时间到,将不再等待。
void join(long millis, int nanos) :等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
package com.dingjiaxiong.api;
/**
* @Projectname: BigDataStudy
* @Classname: TestThreadStateChange
* @Author: Ding Jiaxiong
* @Date:2023/4/27 15:53
*/
public class TestThreadStateChange {
public static void main(String[] args) {
Thread te = new Thread() {
@Override
public void run() {
for (int i = 2; i <= 100; i += 2) {
System.out.println("偶数线程:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
te.start();
Thread to = new Thread() {
@Override
public void run() {
for (int i = 1; i <= 100; i += 2) {
System.out.println("奇数线程:" + i);
if (i == 5) {
// Thread.yield();
try {
te.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
to.start();
}
}
运行效果
9.3.4 如何让线程提前结束
一个线程如何让另一个线程提前结束呢?
线程的死亡有两种:
自然死亡:当一个线程的run方法执行完,线程自然会停止。
意外死亡:当一个线程遇到未捕获处理的异常,也会挂掉。
我们肯定希望是让线程自然死亡更好。
-
public final void stop():强迫线程停止执行。 该方法具有固有的不安全性,已经标记为@Deprecated==(已过时、已废弃)==不建议再使用,那么我们就需要通过其他方式来停止线程了,其中一种方式是使用变量的值的变化来控制线程是否结束。
-
标记法
案例:
声明一个PrintEvenThread线程类,继承Thread类,重写run方法,实现打印[1,100]之间的偶数,要求每隔1毫秒打印1个偶数。
声明一个PrintOddThread线程类,继承Thread类,重写run方法,实现打印[1,100]之间的奇数。
在main线程中:
(1)创建两个线程对象,并启动两个线程
(2)当打印奇数的线程结束了,让偶数的线程也停下来,就算偶数线程没有全部打印完[1,100]之间的偶数。
package com.dingjiaxiong.api;
/**
* @Projectname: BigDataStudy
* @Classname: PrintEvenThread
* @Author: Ding Jiaxiong
* @Date:2023/4/27 15:54
*/
public class PrintEvenThread extends Thread {
private boolean flag = true;
@Override
public void run() {
for (int i = 2; i <= 100 && flag; i += 2) {
System.out.println("偶数线程:" + i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
package com.dingjiaxiong.api;
/**
* @Projectname: BigDataStudy
* @Classname: PrintOddThread
* @Author: Ding Jiaxiong
* @Date:2023/4/27 15:54
*/
public class PrintOddThread extends Thread {
@Override
public void run() {
for (int i = 1; i <= 100; i += 2) {
System.out.println("奇数线程:" + i);
}
}
}
测试类
package com.dingjiaxiong.api;
/**
* @Projectname: BigDataStudy
* @Classname: TestThreadStop
* @Author: Ding Jiaxiong
* @Date:2023/4/27 15:55
*/
public class TestThreadStop {
public static void main(String[] args) {
PrintEvenThread pe = new PrintEvenThread();
PrintOddThread po = new PrintOddThread();
pe.start();
po.start();
try {
po.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
pe.setFlag(false);
}
}
运行结果
9.3.5 守护线程(了解)
有一种线程,它是在后台运行的,它的任务是为其他线程提供服务的,这种线程被称为“守护线程”。JVM的垃圾回收线程就是典型的守护线程。
守护线程有个特点,就是如果所有非守护线程都死亡,那么守护线程自动死亡。
调用setDaemon(true)方法可将指定线程设置为守护线程。必须在线程启动之前设置,否则会报IllegalThreadStateException异常。
调用isDaemon()可以判断线程是否是守护线程。
package com.dingjiaxiong.api;
/**
* @Projectname: BigDataStudy
* @Classname: TestThread
* @Author: Ding Jiaxiong
* @Date:2023/4/27 15:55
*/
public class TestThread {
public static void main(String[] args) {
MyDaemon m = new MyDaemon();
m.setDaemon(true);
m.start();
for (int i = 1; i <= 100; i++) {
System.out.println("main:" + i);
}
}
}
class MyDaemon extends Thread {
public void run() {
while (true) {
System.out.println("我一直守护者你...");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
练习:龟兔赛跑
案例:编写乌龟类(Tortoise)和兔子类(Rabbit), 编写龟兔赛跑多线程程序,设赛跑长度为30米。乌龟和兔子每跑完10米输出一次结果。
- 兔子的速度是10米每秒,兔子每跑完10米休眠的时间10秒。
- 乌龟的速度是1米每秒,乌龟每跑完10米的休眠时间是1秒。
案例完成思路要求:
乌龟定义一个线程,兔子定义一个线程,两个线程同时开启,提示:可以使用Thread.sleep(毫秒数)来模拟耗时。
package com.dingjiaxiong;
/**
* @Projectname: BigDataStudy
* @Classname: TortoiseAndRabbitTest
* @Author: Ding Jiaxiong
* @Date:2023/4/27 15:57
*/
public class TortoiseAndRabbitTest {
public static void main(String[] args) {
Tortoise t = new Tortoise();
Rabbit r = new Rabbit();
new Thread(t).start();
new Thread(r).start();
}
}
class Tortoise implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 30; i++) {
//i代表米数,每次+1代表跑过了一米。
try {
Thread.sleep(1000);//每次循环休眠1一秒,代表一秒钟跑了一米
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("乌龟跑了一米~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
if (i == 30) {
System.out.println("乌龟跑到了终点=============================");
break;
}
if (i % 10 == 0) {
try {
Thread.sleep(1000);//每隔十米乌龟要休眠一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Rabbit implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 1; i <= 30; i++) {
//i代表米数,每次+1代表跑过了一米。
try {
Thread.sleep(100);//每次循环休眠0.1一秒,代表一秒钟跑了十米
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("兔子跑了一米~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
if (i == 30) {
System.out.println("兔子跑到了终点=============================");
break;
}
if (i % 10 == 0) {
try {
Thread.sleep(10000);//每隔十米兔子要休眠是秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果