Java多线程基础
2021/12/20 20:21:38
本文主要是介绍Java多线程基础,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Java多线程基础
- 进程和多线程
- 创建多线程
- 继承Thread类
- 分析线程信息
- 实现Runnable接口
- 线程安全问题
- 常用方法
- currentThread()
- isAlive()
- sleep(long millis)
- sleep(long millis,int nanos)
- StackTranceElement[ ] getStackTrace()
- static void dumpStack()
- getID()
- 停止线程
- interrupt() 方法
- 判断线程是否停止
- interrupt()方法中断线程
- 使用stop() 方法暴力停止线程(不推荐)
- 暂停线程
- yield方法
- 线程优先级
- 守护线程
进程和多线程
进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。
程序:指令序列,用来让cpu完成指定的任务,一个.java程序经过编译形成.class文件,操作系统创建一个JVM虚拟机进程(每执行一次main方法就创建一个JVM进程),并在虚拟机中加载class文件并运行,进程通过创建你新线程来执行具体的任务。
线程:线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
创建多线程
继承Thread类
分析线程信息
使用jdk中的命令分析线程信息
- jps+jstack.ext
- jmc.exe
- jvisualvm.exe
实现Runnable接口
Thread.java类的8个构造方法
- Thread()
分配一个新的 Thread对象。 - Thread(Runnable target)
分配一个新的 Thread对象。 - Thread(Runnable target, String name)
分配一个新的 Thread对象。 - Thread(String name)
分配一个新的 Thread对象。
构造函数Thread(Runnable target) 不仅可以传入Runnable接口对象,而且可以传入一个Thread类的对象。
线程安全问题
在run()方法前添加synchronized关键字,一个线程调用run方法前会判断run方法有没有上锁,如果run方法被上锁,说明其他线程正在调用,必须等待。
synchronized可以对任意对象及方法加锁,被加锁的这段代码称为“互斥区”或“临界区”。
常用方法
currentThread()
返回代码正在被哪个线程调用
run2的构造函数是被main线程调用,run方法是被Thread-0的线程调用
执行方法run()和start()方法的区别:
- run方法:立即执行run方法,不启动新线程。
- start方法:执行run方法的时机不确定,启动新线程。
isAlive()
isAlive方法判断当前线程是否存活
sleep(long millis)
在指定的时间(毫秒)内让当前正在执行的线程休眠,这个当前正在执行的线程是指this.currentThread()返回的线程。
sleep(long millis,int nanos)
在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠
StackTranceElement[ ] getStackTrace()
作用是返回一个表示该线程堆栈跟踪元素数组
static void dumpStack()
将当前线程的堆栈跟踪信息输出到标准错误流
getID()
用于取得线程的唯一标识
停止线程
interrupt() 方法
调用interrupt方法仅仅在当前线程中做了一个停止的标记,并不是真正的停止线程
判断线程是否停止
- public static boolean interrupted() :测试currentThread()是否已经中断,执行后具有清除状态标志值为false的功能。也可以用Thread.interrupted()判断,因为在Thread.java类中调用静态static方法时,大多数是针对currentThread()线程进行操作的
- public boolean this.isIntererupted() :测试this关键字所在类的对象是否已经中断,非静态方法,作用与调用这个方法的对象。不清楚状态标志。
interrupt()方法中断线程
public class MyThread5 extends Thread { @Override public void run() { super.run(); try{ for (int i = 0; i <500000 ; i++) { if(this.isInterrupted()){ System.out.println("已经是停止状态,我要推出了!"); throw new InterruptedException(); //或者不抛异常,直接return } System.out.println("i="+(i+1)); } } catch (InterruptedException e){ System.out.println("进入run方法中的catch了!!"); e.printStackTrace(); } } public static void main(String[] args) { try{ MyThread5 myThread5 = new MyThread5(); myThread5.start(); Thread.sleep(2000); myThread5.interrupt(); } catch (InterruptedException e) { System.out.println("main catch!!"); e.printStackTrace(); } System.out.println("end!!!"); } }
sleep和interrupt
不管调用顺序,只要interrupt()和sleep()方法碰到一起就会出现异常:在sleep状态执行interrupt()方法会出现异常;调用interrupt()方法给线程打上了中断标记,在执行sleep()方法也会出现异常
使用stop() 方法暴力停止线程(不推荐)
public class MyThread6 extends Thread { private int i=0; @Override public void run() { super.run(); try { while (true){ i++; System.out.println("i="+i); Thread.sleep(1000); } } catch (InterruptedException e){ e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { MyThread6 myThread6 = new MyThread6(); myThread6.start(); Thread.sleep(8000); myThread6.stop(); } }
暂停线程
在Java多线程中,可以使用suspend()方法暂停线程,使用resume()方法来恢复线程的执行
suspend()、resume() 方法是过期作废的方法,原因是容易造成公共同步对象被独占,其他线程无法访问公共同步对象的结果,因此想要实现对线程进行暂停与恢复的处理,可以使用wait()、notify()或者notifyAll()方法
System.out.println也是同步方法
yield方法
yield方法的作用是放弃当前的cpu资源,让其他任务去占用cpu执行时间,放弃的时间不确定,有可能刚刚放弃,马上又获得cpu时间片
线程优先级
在Java中线程的优先级分为1-10共10个等级,如果线程优先级小于1或者大于10,则JDK抛出异常 throw new IllegalArguementException()
- 线程优先级的继承特性
在Java中,线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级和A线程的优先级是一样的
public class MyThread10 extends Thread { @Override public void run() { super.run(); System.out.println("MyThread10 run priority="+this.getPriority()); } } public class MyThread9 extends Thread { @Override public void run() { super.run(); System.out.println("MyThread9 run priority="+this.getPriority()); MyThread10 myThread10 = new MyThread10(); myThread10.start(); } public static void main(String[] args) { System.out.println("main thread begin priority="+Thread.currentThread().getPriority()); //Thread.currentThread().setPriority(6); System.out.println("main thread end priority="+Thread.currentThread().getPriority()); MyThread9 myThread9 = new MyThread9(); myThread9.start(); } }
去掉注释
2. 优先级的规律
高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完,CPU尽量将执行资源让给优先级比较高的线程,线程的优先级与执行顺序具有不确定性、随机性
守护线程
Java中有两种线程,一种是用户线程,另一种是守护线程
守护线程是一种特殊线程,当进程中不存在用户线程了,则守护线程自动销毁,典型的守护线程是垃圾回收线程
只用当最后一个用户线程结束时,则守护线程才随着JVM一同结束,守护线程的作用是为其他运行的线程提供服务。
public class MyThread11 extends Thread { private int i=0; @Override public void run() { super.run(); try{ while(true){ i++; System.out.println("i="+(i+1)); Thread.sleep(1000); } } catch (InterruptedException e){ e.printStackTrace(); } } public static void main(String[] args) { try{ MyThread11 myThread11 = new MyThread11(); myThread11.setDaemon(true); myThread11.start(); Thread.sleep(5000); System.out.println("main 结束,守护线程也随之结束!"); } catch (InterruptedException e){ e.printStackTrace(); } } }
这篇关于Java多线程基础的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)