0
点赞
收藏
分享

微信扫一扫

8.动态规划-数字塔

自由的美人鱼 2024-05-06 阅读 10

在这里插入图片描述

目录

1.前言


2.进程

提到线程,我们就不得不先了解进程了,那么什么是进程呢?进程就是运行起来的一个个程序。 引入进程有什么作用呢?是为了实现并发编程。但进程有很多,系统是如何管理它们的呢?那就是"先描述,再组织"


3.线程

线程也叫做“轻量级进程”,创建线程,销毁线程,调度线程都比进程更快。但线程不能独立存在,要依附于进程,即一个进程至少包含一个线程!但每一个线程都是独立执行的,一个进程,最开始的时候必须要包含一个线程,这个线程负责完成执行代码的工作,也可以创建出多个线程,完成并发执行的效果。


4.线程和进程的区别


5.Thread创建线程

线程是操作系统的概念,操作系统提供了一些API可以操作线程,Java对系统API进行了封装,使用Thread类就可以创建出一个线程.

5.1继承Thread创建线程

方法1:

package Thread;
class MyThread extends Thread{
    @Override
    //线程的入口
    public void run() {
        while (true) {
            System.out.println("hello thread");
			//隔1s轮转
            try {
                Thread.sleep(1000);//1s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new MyThread();
        //start和run都是Thread的成员
        //run只是描述线程的入口,线程主要做什么
        //start则是真正的调用了系统API创建了线程,让线程再调用run()
        t.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }

    }
}

方法2:匿名内部类

package thread;
public class Demo3 {
    public static void main(String[] args) {
        Thread t = new Thread() {
        //匿名内部类
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t.start();
        while (true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

注意
1.Thread在java.lang这个包下并不用导包
2.start方法内部会调用系统的API生成一个线程再调用run函数,和run函数的效果类似,但本质区别为:是否会创建一个线程


5.2实现Runnable接口

方法1:

package thread;
class MyRunnable implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Runnable runnable = new MyRunnable();
        Thread t = new Thread(runnable);
        t.start();
        while (true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

方法2:匿名内部类

package thread;
public class Demo4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();
        while (true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

5.3lambda表达式

package thread;
public class Demo6 {
    public static void main(String[] args) {
     //lambda表达式
        Thread t = new Thread(() -> {
            while (true) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"第一个线程");
       t.start();
       while (true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

6.Thread常见方法

6.1Thread常见属性

属性获取方法
IDgetId
名称getName
状态getState
优先级getPriority
是否后台线程isDaemon
是否存活isAlive
是否被中断isInterrupted

6.2 中段一个线程- interrupt()

首先我们要知道,一个线程如果时间特别长,那么大概率在线程的内部有循环再一直执行。如果想要中断此线程,那么我们就想办法尽快让run函数执行完成,那么怎么能让循环快速执行完呢?其实我们只需要在循环处添加一个条件,条件不成立就结束了。
例如:

public class Demo7 {
    public static boolean  flag=false;
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{
            while (!flag){
                System.out.println("t进程");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("工作完毕");
        });
        t.start();
        Thread.sleep(5000);
        flag=true;
        System.out.println("打断进程");
    }
}

注意
定义flag的时候只能定义为成员变量,不能定义为局部变量,因为在lambda有一个语法规则:变量捕获。把当前作用域的变量在lambda中复制了一份,在变量捕获时有一个前提限制:必须只能捕获final修饰的变量或者变量不能做任何修改。如果把flag设置为成员变量,就不再是变量捕获的与法律,而是内部类访问外部类的属性。

但是如果我们每次都专门定义一个标志位来打断线程是非常麻烦的,而且当处于睡眠模式下还不能立即就想应,在Thread类中有有一个标志位isInterupted来判定线程是否被打断。

public class Demo8 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("t进程");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //唤醒sleep有3种操作
                    //1.不管它,继续执行t线程
                    //2.立即执行打断
                    break;
                    //3.进行一些其他操作
                }
            }
        });
        t.start();
        System.out.println("main进程");
        Thread.sleep(5000);
        System.out.println("t进程打断");
        t.interrupt();//打断
    }
}

说明
1.Thread.currentThread()表示当前线程即t线程
2.在正常情况下,sleep休眠时间完成才会被唤醒,如果调用interrupt()那么就提提前唤醒它触发InterruptedException异常
观察下图:虽然打断了t线程并且触发了InterruptedException异常,但t线程依然在执行。
在这里插入图片描述
出现上述情况是因为:interr唤醒sleep之后会抛出异常当同时也会清除标志位,这就使打断效果像没有生效一样。Java期望当线程收到“要中断”的信号使,由本身来决定接下来该怎么做。

6.3等待线程-jion()

等待一个线程即使指,当一个线程执行完毕时才能执行另外一个线程。

public class Demo9 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{
            for (int i=0;i<5;i++){
                System.out.println("t线程正在执行");
            }
        });
        t.start();
        //等待t线程执行结束再执行main线程
        t.join();
        System.out.println("t线程执行结束");
        System.out.println("main线程");

    }
}

7.线程的状态

在进程中最核心的状态就是就绪和阻塞状态,在线程中同样适用,同时java又赋予了线程一些其他的状态:

2.1代码实现

public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{
            for (int i=0;i<3;i++){
                System.out.println("t线程在执行");
            }
        });
        System.out.println(t.getState());
        t.start();
        System.out.println(t.getState());
       Thread.sleep(3000);
        System.out.println(t.getState());
    }
}

2.2运行结果

在这里插入图片描述

下期预告:线程安全问题

举报

相关推荐

0 条评论