结合多本著作和个人开发经验,整理Java多线程入门手册(3)
上一篇 /
下一篇 2023-02-03 10:54:01
设置线程名
实现类:
public class RunnableImpl implements Runnable{
@Override
public void run() {
// 输出10以内偶数
for (int i = 0; i < 10; i++) {
if (i % 2 == 0){
// 获取当前线程
Thread thread = Thread.currentThread();
// 获取线程名
String threadName = thread.getName();
System.out.println(threadName + "===>" + i);
}
}
}
}
public class RunnableMain {
public static void main(String[] args) {
// 1、创建实现类对象
RunnableImpl runnable = new RunnableImpl();
// 2、 创建线程对象,并指定线程名
Thread t1 = new Thread(runnable, "线程1");
// 3、启动线程
t1.start();
System.out.println(Thread.currentThread().getName() + "主线程");
}
}
运行结果:
或者通过setName()方法设置线程名:
public class RunnableMain {
public static void main(String[] args) {
// 1、创建实现类对象
RunnableImpl runnable = new RunnableImpl();
// 2、 创建线程对象,不指定名字
Thread t1 = new Thread(runnable);
// 设置线程名
t1.setName("线程1");
// 3、启动线程
t1.start();
System.out.println(Thread.currentThread().getName() + "主线程");
}
}
如果不设置线程名,默认为【"Thread-" + nextThreadNum()】,nextThreadNum方法使用 threadInitNumber静态变量,默认从0开始,每次+1。
不设置线程名运行效果如下:
sleep方法
sleep方法可以让线程阻塞指定的毫秒数。时间到了后,线程进入就绪状态。sleep可用来研模拟网络延时,倒计时等。每一个对象都有一个锁,sleep不会释放锁,锁的概念后边会详细讲解
实现类:
public class RunnableImpl implements Runnable{
@Override
public void run() {
// 输出10以内偶数
for (int i = 0; i < 10; i++) {
if (i % 2 == 0){
try {
// 休眠1秒
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "===>" + i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
测试类:
public class RunnableMain {
public static void main(String[] args) {
// 1、创建实现类对象
RunnableImpl runnable = new RunnableImpl();
// 2、 创建线程对象,不指定名字
Thread t1 = new Thread(runnable,"线程1");
// 3、启动线程
t1.start();
}
}
运行结果:
"善用"sleep年入百万不是梦:
yield方法
提出申请释放CPU资源,至于能否成功释放取决于JVM决定,调用yield()方法后,线程仍然处于RUNNABLE状态,线程不会进入阻塞状态,保留了随时被调用的权利
实现类:
public class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "执行结束");
}
}
测试类:
public class RunnableMain {
public static void main(String[] args) {
// 1、创建实现类对象
RunnableImpl runnable = new RunnableImpl();
// 2、 创建线程对象,不指定名字
Thread t1 = new Thread(runnable,"线程1");
Thread t2 = new Thread(runnable,"线程2");
// 3、启动线程
t1.start();
t2.start();
}
}
运行结果:
第五次执行是线程2执行开始结束后输出的线程1开始结束,这就说明CPU并没有切换到别的线程,说明并没有释放CPU资源。
join方法
将当前的线程挂起,当前线程阻塞,待其他的线程执行完毕,当前线程才能执行,可以把join()方法理解为插队,谁插到前面,谁先执行。
在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将可能早于子线程结束。如果主线程需要知道子线程的执行结果时,就需要等待子线程执行结束了。主线程可以sleep(xx),但这样的xx时间不好确定,因为子线程的执行时间不确定,join()方法比较合适这个场景。
public class RunnableMain {
public static void main(String[] args) {
// 1、lambda创建线程
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
// 模拟耗时操作
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "join方法===>" + i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
// 2、 启动线程
t1.start();
try {
// t1调用join 方法
t1.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("main线程");
}
}
运行结果:
设置优先级
改变、获取线程的优先级。
Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。线程的优先级用数据表示,范围1~10。线程的优先级高只是表示他的权重大,获取CPU执行权的几率大。先设置线程的优先级,在执行start()方法。
public class RunnableMain {
public static void main(String[] args) {
// 1、lambda创建线程
Thread t1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "线程优先级" + Thread.currentThread().getPriority());
},"线程1");
Thread t2 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "线程优先级" + Thread.currentThread().getPriority());
},"线程2");
// 2、设置线程优先级
t1.setPriority(1);
t2.setPriority(10);
// 3、 启动线程
t1.start();
t2.start();
System.out.println("main线程");
}
}
结束线程
JDK提供的【stop()、destroy()】两种方法已废弃,不推荐再使用。推荐线程自动停止下来,就比如上边的所有案例,都是执行完了run方法中的所有代码之后线程就自然结束了。如果线程需要循环执行,建议使用一个标识位变量进行终止,当flag=false时,则终止线程运行
比如:定义一个名为【线程1】的子线程,当主线程执行3次循环之后,线程1停止运行
实现类:
public class RunnableImpl implements Runnable{
// boolean变量标记是否需要继续执行
private boolean flag = true;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
// 循环执行,flag为false时停止
while (flag) {
System.out.println(Thread.currentThread().getName() + "正在运行");
}
}
}
测试类:
public class RunnableMain {
public static void main(String[] args) {
RunnableImpl runnable = new RunnableImpl();
Thread t1 = new Thread(runnable, "线程1");
t1.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程====》" + i);
// 当循环三次时
if(i == 3) {
// 设置flag值为false
runnable.setFlag(false);
}
}
}
}
总结
· 熟练创建和启动线程
· 掌握线程状态和状态之间转换
· 掌握Thread类中的常用方法如:join、sleep、yield等
收藏
举报
TAG:
Java
java
多线程