Java线程状态
首先,了解Java线程状态的时候,查了一下相关的文章,然后总结得出的相关内容,对线程的相关状态进行自己的总结,线程的基本状态连了解个大概,如图:
线程的方法
既然清楚了线程的大致的流程状态,那就得了解一下,线程上的方法,然后下面是讲解一下某个方法的详细使用情况。
方法名称 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 指定的毫秒数内让当前正在执行的线程睡眠 |
void join() | 等待线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程(不建议使用该方法) |
boolean isAlive() | 测试线程是否处于活动状态 |
关于线程的停止
其实只要去看一下线程Thrread类就会发现,关于线程停止的方法基本上都已经不推荐是有了,都标记了
@Deprecated 分别是 stop() , suspend(), resume(), destroy()等,既然官方不推荐使,就说明这些方法随着JDK版本的迭代更新后,已经不适用了,所以关于线程的如何停止线程一般是以下2种方法
1.让线程完整地执行完毕(推荐,优先考虑)
这个就是让线程完整地执行完成,这样线程就会自动停止了
2.自行代码控制流程的执行情况,比如做个标识位
做一个标识符,当达到某个条件是,线程代码停止执行。
public class RunnableDemo1 implements Runnable {
//控制流程是否停止
private boolean flag = true;
@Override
public void run() {
while (flag) {
System.out.println("我正在执行我的线程内容");
}
}
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
//创建线程,并进入就绪状态
RunnableDemo1 runnableDemo = new RunnableDemo1();
new Thread(runnableDemo).start();
//添加循环,给足够的时间让程序调用线程,这个时候我们再执行停止方法
for (int i = 0; i<1000000; i++) {
if(i == 999999) {
runnableDemo.stop();
}
}
}
}
线程睡眠
关于线程的睡眠,就是智sleep方法。关于sleep方法的展开的内容,进行说明
- sleep是指当前线程阻塞的毫秒数
- 使用sleep方法存在InterruptedException异常
- sleep时间结束后,线程重新进入就绪状态
- sleep可以模拟网络延迟,倒计时等
- sleep不会释放锁
线程的礼让
关于线程的礼让,就是让当前正在执行的 线程停止,但不阻塞,礼让后,线程将会从运行的状态转为就绪的状态 ,从而让程序重新调用。但是这个礼让不一定会成功。所以并不是百分百的。相关实验效果可以方法执行下列代码就会发现的
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield, "a").start();
new Thread(myYield, "b").start();
//结果1 礼让了,但是没有成功的执行结果
//a:线程开始执行
//a:线程停止执行
//b:线程开始执行
//b:线程停止执行
//结果2
//a:线程开始执行
//b:线程开始执行
//a:线程停止执行
//b:线程停止执行
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+":线程停止执行");
}
}
强制执行
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i< 100; i++) {
System.out.println("VIP来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
for (int i = 0; i<200; i++) {
System.out.println("正在排队");
if(i == 199) {
//插队执行
System.out.println("开始插队了");
thread.join();
}
}
}
}
线程的状态
查看JDK文档或者查看Thread的远吗就会发现,其实线程是存在5种状态的,分别是
State | 说明 |
---|---|
NEW | 尚未启动的线程处于此状态 |
RUNNABLE | 在Java虚拟机种执行的线程 |
BLOCKED | 被阻塞等待监视器锁定的线程 |
WAITING | 正在等待另外一个线程执行特定动作的线程 |
TIMED_WAITING | 正在等待另外一个线程执行动作到达指定等待时间的线程 |
TERMINATED | 已经退出的线程 |
备注:一个线程可以给定时间点处于一个状态,这些状态是不反应任何操作系统线程的状态的虚拟机状态
简易的线程状态观测代码如下:
public class TestStaate {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for (int i = 0; i < 5; i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("循环结束了");
});
//观察状态
Thread.State state = thread.getState();
//NEW状态
System.out.println(state);
//启动后的 RUNNABLE
thread.start();
state = thread.getState();
System.out.println(state);
//只要线程不终止,就输出线程状态
while (state != Thread.State.TERMINATED) {
Thread.sleep(100);
state = thread.getState();
System.out.println(state);
}
}
}
线程优先级
Java提供了一个线程调度器程序中启动后进入就绪状态的所有线程。线程调度都是安装优先级决定调度那个线程来执行的,线程优先级用数字标识,范围是1~10理论上,只要数字越大,被优先调用的概率越高,优先级并不是百分百的。线程创建的默认级别是5
public class TestPriority {
public static void main(String[] args) {
//主线程的默认优先级
System.out.println("主线程默认的优先级:" +Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);
Thread t7 = new Thread(myPriority);
//先设置优先级再启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);
t4.start();
//源码上看到,超过10,低于1的都会报错
/*t5.setPriority(-1);
t5.start();
t6.setPriority(11);
t6.start();*/
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority());
}
}
守护线程
首先,线程分为用户线程和守护线程,而且虚拟机必须确保用户线程执行完毕,虚拟机不用等待守护线程执行完毕(如:后台记录操作入职,监控内存,垃圾回收等待等)
//测试守护线程
public class TestDemon {
public static void main(String[] args) {
MyDemon myDemon = new MyDemon();
GuardDemon guardDemon = new GuardDemon();
//守护线程
Thread thread = new Thread(guardDemon);
thread.setDaemon(Boolean.TRUE);
thread.start();
new Thread(myDemon).start();
}
}
class GuardDemon implements Runnable{
@Override
public void run(){
while (true){
System.out.println("正在守护中");
}
}
}
class MyDemon implements Runnable{
@Override
public void run() {
for (int i = 0; i<36500; i++){
System.out.println("正在执行线程的内容");
}
System.out.println("=======>> 我的线程结束了");
}
}
线程同步
线程同就是,存在多个线程访问一个资源的情况。俗称并发。实现线程同步安全的方法就是队列加锁,才可以保证线程的安全性。有锁就代表着一个线程有锁的情况下其他所有需要此锁的线程的挂起,在多线程竞争下,加锁,是否锁都会导致比较多的上下文切换,调度延时,引起性能问题,如果一个优先级搞的线程等待一个优先级底的电池释放锁,会导致优先级倒置,引起线程性能问题。线程安全是回导致一部分性能下降。鱼和熊掌不可兼得。