当前位置: 首页 > news >正文

湖北营销型网站建设做网站到a5卖站赚钱

湖北营销型网站建设,做网站到a5卖站赚钱,网站建设购买模板,上海品牌建站Java Web 实战 03 - 多线程基础篇 2二 . Thread类常见方法2.1 Thread 的常见构造方法2.2 Thread 的几个常见属性getId()getName()getState()getPriority()isDaemon()案例 : 实现 getId()、getName()、 getState()、getPriority()、isDaemon()、isAlive()2.3 启动一个线程-start… Java Web 实战 03 - 多线程基础篇 2二 . Thread类常见方法2.1 Thread 的常见构造方法2.2 Thread 的几个常见属性getId()getName()getState()getPriority()isDaemon()案例 : 实现 getId()、getName()、 getState()、getPriority()、isDaemon()、isAlive()2.3 启动一个线程-start()2.4 中断线程(线程执行结束)2.4.1 手动创建的标志位2.4.2 Thread自带的标志位2.5 线程等待 join2.5.1 join 是怎么回事?2.5.2 栗子1 : 让 main 等待 t2 , t2 去等待 t12.5.3 栗子2 : 控制 main 先运行 t1 , t1 执行完再运行 t22.5.4 带参数版本的 join2.6 获取到线程引用 : Thread.currentThread()2.7 线程的休眠 : sleep三 . 线程的状态3.1 通过代码来看线程的状态3.2 线程状态和状态转移的意义大家好 , 这篇文章给大家带来的是多线程相关的基础知识 , 我们会介绍一下Thread 类常见的方法都有什么 , 以及启动线程、中断线程、线程等待、获取线程引用、现成的休眠等问题 , 然后再给大家介绍一下线程的状态都有什么这几个问题。 上一篇文章的链接在这里 , 大家移步观看 http://t.csdn.cn/JVErX 由于 C 站的编辑器不太好用 , 导致许多排版没能生效 , 大家可移步至这里观看 https://www.yuque.com/jialebihaitao/study/qzym2pw332lm6k7q?singleDoc# 《2. 多线程 (基础)》 感谢大家的支持~ 二 . Thread类常见方法 2.1 Thread 的常见构造方法 方法说明Thread()创建线程对象 (已经用过了)Thread(Runnable target)使用 Runnable 对象创建线程对象Thread(String name)创建线程对象并命名Thread(Runnable target, String name)使用 Runnable 对象创建线程对象并命名 其中第一个和第二个我们已经使用过 Thread() : 自己创建线程的子类 , 再去 new 他的实例 Thread t new MyThread();Thread(Runnable target) : 使用 Runnable 创建一个任务 , 然后将 Runnable 的任务放到线程中 , 这样也可以创建一个线程 Runnable runnable new MyRunnable(); Thread t new Thread(runnable);Thread(String name) : 这个操作是给线程起名字我们之前看到的 Thread-0 就是 Java 帮我们命名的线程在操作系统里面是没有名字的Java 为了帮助程序员便于理解就在 JVM 里面给对应的 Thread 对象起了个名这个线程是和内核中的线程一一对应的 , 这个名字对于程序的执行 , 没有任何影响 , 对于程序员来说调试挺有用的 Thread t3 new Thread(这是我的名字);Thread(Runnable target, String name) : 既实现了命名 , 又实现了使用 Runnable 对象创建线程对象 public class Demo7 {public static void main(String[] args) {Thread t new Thread(new Runnable() {Overridepublic void run() {while(true) {System.out.println(Hello MyThread);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();}}} } 我们使用 jconsole 工具查看当前线程 , 就发现有我们自己重新命名的线程了 2.2 Thread 的几个常见属性 属性获取方法IDgetId()名称getName()状态getState()优先级getPriority()是否后台线程isDaemon()是否存活isAlive()是否被中断isinterrupted() getId() 获取到的是 线程 在 JVM 里面的身份标识 线程里面的身份标识是有好几个的 内核的 PCB 上有标识用户态线程库里面也有标识 (pthread , 操作系统提供的线程库)JVM里面也有标识 (JVM 的 Thread 类底层也是调用操作系统的 pThread 库) 这三个标识各不相同但是目的都是作为身份的区分我们可以理解为身份标识的各种小名 getName() 获取在Thread的构造方法里面传入的姓名 (刚才在 Thread 构造方法中传入的名字) getState() 获取到 PCB 里面的状态 , 这个状态表示线程当前所处的一个情况 . 此处得到的状态是 JVM 里面设立的状态体系 , 这个状态比操作系统内置的状态要更丰富 getPriority() 获取到线程的优先级 , 优先级高的线程理论上来说更容易被调度到 isDaemon() 判断是不是后台线程 Daemon的意思是 “守护线程” 的意思 , 我们可以理解为 “后台线程” 线程分为前台线程与后台线程 , 我们可以通过类比手机的正在运行应用 (前台应用) 与后台应用来理解前台线程与后台线程 一个线程 , 创建出来默认就是前台线程 , 前台线程会阻止进程结束 , 进程会保证所有的前台线程都执行完毕 , 才会退出 . main 线程就是一个前台线程 如果我们屏蔽了 main 线程 , 正常情况下线程就会退出 但是运行并非如此 这是因为我们上面新建的线程默认就是前台线程 , 我们需要将自己创建的线程修改成后台线程 public class Demo7 {public static void main(String[] args) {Thread t new Thread(new Runnable() {Overridepublic void run() {while(true) {System.out.println(Hello MyThread);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}},俺的线程);t.setDaemon(true);// 设置成后台线程t.start();// while(true) {// System.out.println(Hello main);// try {// Thread.sleep(1000);// } catch (InterruptedException e) {// e.printStackTrace();// }// }} } 这样我们的线程就会嗖的一下执行完 有个小问题 : ❗ 我们发现 , 怎么运行了多次 , 怎么有的时候打印有的时候就不打印呢? ✅ 举个栗子 : 当我们刚打完一局游戏 , 想要打开 B 站去学习 , 这时候点开了 B 站 , B 站这个时候就是前台应用 , 必须是在执行的 , 不能被销毁 前台线程 : 前台线程会阻止进程结束 , 一个线程创建出来默认就是前台线程 , 进程会保证所有前台进程执行完毕才结束程序 后台的游戏就被隐藏到任务栏里面了 , 其实还运不运行已经无所谓了 , 因为我们已经玩完了 后台线程 : 后台线程不会阻止进程结束 , 比如 : main线程执行结束 , 整个线程就结束了 这是因为我们把 t 线程设置成了后台线程 , 当 main线程执行完毕整个程序就执行完了 , 我们这里并未对 main 线程做任何操作 , 所以有可能是在 main 线程结束之前运行了一下 t 线程 , 也有可能是直接就执行结束了 , t 线程还没来得及执行 案例 : 实现 getId()、getName()、 getState()、getPriority()、isDaemon()、isAlive() 接下来 , 我们写一个方法 , 来实现 getId()、getName()、 getState()、getPriority()、isDaemon()、isAlive() public class Demo8 {public static void main(String[] args) {Thread t new Thread(() - {while (true) {System.out.println(Hello MyThread);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}},俺的线程);System.out.println(t.getId());// 获取线程IDSystem.out.println(t.getName());// 获取线程名称System.out.println(t.getState());// 获取线程状态System.out.println(t.getPriority());// 获取线程优先级System.out.println(t.isDaemon());// 获取是否是后台线程System.out.println(t.isAlive());// 获取线程是否存活} } 2.3 启动一个线程-start() 我们之前已经使用过这个方法了 给大家强调一点 : (安排任务)创建 Thread 实例 , 并没有真正的在操作系统内核中创建出线程 . 这里的任务是通过 Thread 的 run 或者 Runnable 或者 lambda 来体现具体的任务内容 run 方法只是描述任务 , 这一点要与 start 方法区分开 (发令枪响)调用 start 方法 , 才是真正在系统里创建出线程 , 才真正开始执行任务 2.4 中断线程(线程执行结束) 线程的执行结束 , 其实就是让线程的入口方法执行完成 , 线程也就执行结束了 普通线程的入口方法就是 run 方法 主线程的入口方法就是 main 方法 那么我们想要中断线程 , 其实就只需要把线程的入口方法执行结束即可 我们有两种方法来中断线程 2.4.1 手动创建的标志位 我们可以自己设置个标志位来区分线程是否要结束 public class Demo11 {// 用一个布尔变量表示线程是否要结束// 注意使用成员变量private static boolean flag false;public static void main(String[] args) {Thread t new Thread(() - {while(!flag) {System.out.println(线程运行中...);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(新线程执行结束...);});t.start();try {Thread.sleep(5000);//休息5s} catch (InterruptedException e) {e.printStackTrace();}System.out.println(这里可以控制新线程退出);flag true;} }这种方案是可行的 , 其实 Thread 自己就提供了这种方法 , 内置了标志位 , 就不需要我们自己创建了 2.4.2 Thread自带的标志位 获取到当前线程的实例:Thread.currentThread() // currentThread是静态方法,.的方式就可以调用他的方法获取内置的标志位的值:Thread.currentThread().isInterrupted() // 为true表示要被结束修改标志位(控制进程退出):t.interrupt();public class Demo9 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {while(!Thread.currentThread().isInterrupted()) {System.out.println(线程运行中~);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();Thread.sleep(5000);System.out.println(控制新线程退出);t.interrupt();} } 我们运行之后发现 , 5s之后程序报错了 , 报错之后还在继续运行 异常是出现了 , 但是线程好像还在继续进行 这里我们就需要理解 interrupt 方法的行为 : 如果 t 线程没有处在阻塞状态(处在运行状态) , 此时 interrupt 就会修改内置的标志位 如果 t 线程处在阻塞状态 , 此时 interrupt 就会让线程内部产生异常的方法 , 例如 : interrupt 让线程里的 sleep 方法 , 抛出一个 InterruptedException 的异常. 异常被 catch 捕获了 , 但是捕获之后 , 啥也没干 , 只是打印了个调用栈 如果我们把打印栈注释掉 , 那么这次什么都不会打印 这就相当于把异常信息捕获之后 , 啥也没干 , 略过去了 正是因为这样的捕获行为 , 程序员就需要自己控制线程的退出行为了 1. 可以立即退出public class Demo9 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {while(!Thread.currentThread().isInterrupted()) {System.out.println(线程运行中~);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();// 1. 立即退出break;}}});t.start();Thread.sleep(5000);System.out.println(控制新线程退出);t.interrupt();} } 2. 也可以稍后退出public class Demo9 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {while (!Thread.currentThread().isInterrupted()) {System.out.println(线程运行中~);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();// 2. 稍后退出System.out.println(新线程即将退出);try {Thread.sleep(5000);} catch (InterruptedException ex) {ex.printStackTrace();}break;}}System.out.println(新线程已经退出);});t.start();Thread.sleep(5000);System.out.println(控制新线程退出);t.interrupt();} } 3. 就不退出 : 啥都不干 , 就是忽略了异常主线程发出 “退出” 命令的时候 , 新线程自己决定如何处理退出的行为 比如 : 室友叫你去食堂 立即跟室友去食堂 [立即退出]打完这局再去 [稍后退出]装没听见 [不去退出] 另外我们在定义的部分是这样说的 : 如果 t 线程处在阻塞状态 , 此时 interrupt 就会让线程内部产生阻塞的方法 他的意思就是 interrupt 不会自己抛出异常 , 他会在中间捣乱 , 让线程内部的 sleep 抛出异常 除了上述方法 , 判定标志位还有另一种方法 : Thread.interrupted() 这种方法的标志位会自动清除 比如 : 刚开始的时候 , 我们去控制他中断 , 这里的标志位先设为 true 等到读取的时候会读到这个 true , 但是读取完之后这个标志位就自动恢复成 false 了 就类似于开关 : 开关一按 , 自己就又弹起来了 而我们上面讲的 Thread.currentThread().isInterrupted()就是开关按下去 , 就不弹起来了 我再帮大家梳理一下思路 2.5 线程等待 join 2.5.1 join 是怎么回事? 我们知道 , 线程之间的执行顺序是完全随机的 , 是由系统决定的 . 但是我们对于这种随机性的东西很头疼 , 所以让顺序能够确定下来 , join 关键字就应运而生. join 就是一种确定线程执行顺序的辅助手段 咱们虽然不能决定多个线程开始的顺序 , 但是这回有了 join , 我们就可以决定结束的顺序了. 还是看一下我们之前的代码 public class Demo8 {private static final long num 20_0000_0000;public static void concurrency() {long begin_time System.currentTimeMillis();Thread t1 new Thread(() - {long a 0;for (long i 0; i num; i) {a;}});Thread t2 new Thread(() - {long b 0;for (long i 0; i num; i) {b;}});t1.start();t2.start();try {t1.join();t2.join();} catch (InterruptedException e) {e.printStackTrace();}long end_time System.currentTimeMillis();System.out.println(多线程消耗的时间: (end_time - begin_time) ms);}public static void main(String[] args) {concurrency();} }在这里面 , main t1 t2 三个线程是随机调度执行的 那么此处的需求 , 就是希望让 t1 和 t2 都执行完了之后 , main 再开始计时 , 来统计执行时间 也就是让 t1 和 t2 先执行完 , main 后执行完 虽然我们无法干预调度器的行为 , 但是我们可以控制 main 线程主动的去进行等待 , 所以我们在 main 线程中分别调用了 t1.join() [main 阻塞 , 等待 t1 执行完]、t2.join() [main 阻塞 , 等待 t2 执行完] 当 t1 t2 都执行完毕 , main 解除阻塞 , 然后程序继续向下执行 , 才能执行完 可以类比领导与职工 , 我们的 main 线程就是 领导 , 我们的 t1 线程和 t2 线程就是员工 早上上班 , 领导给两位职工派活 接下来 , 领导就一直摸鱼 , 等待 t1 和 t2 汇报成果 直到 t1 和 t2 完成工作 , main 线程拿过来验收 , 整个流程才算完事 谁先调用 join 谁后调用 join 都是无所谓的 我们想让谁阻塞 , 谁就调用 join 即可 比如我们想让 t1 以及 t2 阻塞 我们就在 main 线程中调用 t1.join() t2.join() 即可 但是 main 线程比较特殊 , 没有这样的写法 main.join(), 剩下其他自己创建的线程 , 都可以 join 另外 , join 自身也是有可能发生阻塞的 , 所以我们也要去处理一下异常 try {t1.join();t2.join(); } catch (InterruptedException e) {e.printStackTrace(); }join 的行为 : 如果被等待的线程还没执行完 , 就阻塞等待如果等待的线程已经执行完了 , 直接就返回 2.5.2 栗子1 : 让 main 等待 t2 , t2 去等待 t1 让 main 调用 t2.join() , 让 t2 调用 t1.join() public class Demo13 {//先创建两个线程,但是不指向任何元素,方便后面访问private static Thread t1 null;private static Thread t2 null;public static void main(String[] args) throws InterruptedException {System.out.println(main开始);t1 new Thread(() - {System.out.println(t1开始);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t1结束);});t1.start();t2 new Thread(() - {System.out.println(t2开始);try {t1.join();//让t2等待t1执行完再去执行} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t2结束);});t2.start();t2.join();//main等待t2System.out.println(main结束);} }2.5.3 栗子2 : 控制 main 先运行 t1 , t1 执行完再运行 t2 实际上就是谁后调用 join , 谁就后结束 所以先调用 t1.join(), 后调用 t2.join() 就代表让 t1 先执行完 , t2 后执行完 , 就达到我们想要的结果了 public class Demo10 {public static void main(String[] args) throws InterruptedException {System.out.println(main 开始);Thread t1 new Thread(() - {System.out.println(t1 开始);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t1 结束);});t1.start();t1.join();Thread t2 new Thread(() - {System.out.println(t2 开始);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t2 结束);});t2.start();t2.join();System.out.println(main 结束);} } 2.5.4 带参数版本的 join 函数作用public void join()死等线程结束 (不见不散)public void join(long mills)设定了最大等待时间public void join(long mills,int nanos)传了更加精确的时间 未来实际开发程序的时候 , 像这种的等待操作 , 一般不会采用死等的方式 , 这种方式有风险 ! 万一代码出了 bug 没控制好 , 死等就容易让服务器卡死 , 无法继续工作 . 其中 , public void join(long mills,int nanos)这个方法 , 第一个参数传的是毫秒 , 第二个参数传的是纳秒 , 比如第一个参数是 100 , 第二个参数是 1000 , 相当于等待了 100.001 ms 2.6 获取到线程引用 : Thread.currentThread() 为了对线程进行操作(线程等待、线程中断、获取各种线程的属性…) , 就需要获取到线程引用 这个方法我们刚才已经用到了 Thread.currentThread();在线程操作之前 , 我们需要先获取到线程的引用 , 才能对线程进行具体操作 如果是继承 Thread , 然后重写 run 方法的话 , 可以直接在 run 中使用 this 即可获取到线程的实例 但是如果是 Runnable 或者 lambda , this 的方式就不可以了 , 这两种情况下 , this 就不是指向 Thread 实例 所以更通用的办法就是使用 Thread.currentThread(), 这是一个静态方法 , 哪个线程调用这个方法 , 得到的结果就是哪个线程的实例 , 以后获取到线程实例 , 我们就无脑使用这个方法即可 2.7 线程的休眠 : sleep sleep 能让线程休眠一会 我们先讲解一下 相关的原理 那么关于 PCB , 由于我们之前只介绍了进程 , 但是现在新学了线程 , PCB 这个概念还是需要重新提一下的 一组进程包含多组线程 , 每个线程都有自己的 PCB , 那么每一组进程其实就是对应一组 PCB 了 但是同一个进程里面的若干 PCB 还是有关联的 PCB里面有一个 “线程组ID” , 是一样的PCB 里面的内存指针和文件描述符表 , 都是一样的 三 . 线程的状态 我们之前介绍过就绪状态与阻塞状态 , 在 Java / JVM 中 , 对于线程的状态 , 做了一个更明确的区分 NEW: 安排了工作, 还未开始行动 RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作. BLOCKED: 这几个都表示排队等着其他事情 WAITING: 这几个都表示排队等着其他事情 TIMED_WAITING: 这几个都表示排队等着其他事情 TERMINATED: 工作完成了 3.1 通过代码来看线程的状态 public class Demo13 {public static void main(String[] args) throws InterruptedException {Thread t new Thread(() - {System.out.println(Hello Thread);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});// NEW 状态:// 在 start 之前获取// 获取到的是线程还未创建的状态System.out.println(t.getState());t.start();// RUNNABLE 状态// 线程就绪状态// 线程正在工作中System.out.println(t.getState());// TIMED_WAITING 状态// 线程调用了 sleep 方法Thread.sleep(500);System.out.println(t.getState());t.join();// 等待t线程结束// TERMINATED 状态// 在 join 之后获取// 获取到的是线程已经结束后的状态System.out.println(t.getState());} } 3.2 线程状态和状态转移的意义 这个图看起来吓人 , 实际上我们可以简化成下面这样 我们再给大家简单介绍一个方法 : yield yield 的作用是让调用者暂时放弃CPU , 回到阻塞队列里面去排队 我们可以粗暴的理解成 sleep(0) 用的不多 , 有印象即可 关于 yield , 举个栗子 : 我跟我的妈妈去超市 , 到结账的位置了 , 她突然想起来 “艾玛 , 忘打酱油了” , 让我继续排队 , 但是我都要交钱了她还没回来 , 这就很尴尬 . 那么 yield 就是我让后面结账的那个人先结账 , 我的妈妈要是还没回来 , 那就再让后面的人继续往前去结账 , 这就相当于我们一直没出就绪队列 . sleep(0)的意思就是我觉得不好意思了 , 刚退出队伍 , 我妈妈就赶回来了 , 我又赶紧回去队伍 , 这就是出了阻塞队列然后又立马回来了 yield 就是短暂的放弃 CPU , 排到就绪队列中的后面位置 (还是在就绪队列中 , 没进阻塞队列) slepp(0) 就是马上进入阻塞队列 , 又马上回就绪队列 , 效果和 sleep 类似
http://www.dnsts.com.cn/news/39225.html

相关文章:

  • 如何在网站做直播间企业型网站中的文章更新是指什么
  • 网站建设与运营考试图书租借网站 开发
  • 在网站的主页制作时 填写关键字怎么做网站埋点
  • 企业网站怎做网站色调搭配
  • 做宝玉石交易的网站有哪些哪家企业建设网站好
  • 做网站论文网站建设计划书范文
  • 做跨境的网站有哪些内容中国纪检监察报社长
  • 沥林行业网站建设jsp做网站实例教程
  • 外贸网站seo有哪些公司晟合建设集团网站
  • 丰都网站建设公司wordpress自建图床
  • 小规模开普票网站建设几个点360建筑网的内容百度可以查到吗
  • 如何创建网站快捷方式到桌面做地方分类信息网站需要什么资质吗
  • 问答系统网站建设2015做导航网站有哪些功能
  • h5响应式网站模板下载七星互联免费主机
  • 做网站多少钱西宁君博领先怎么做网页背景
  • 专做尼泊尔的旅行网站开发公司企业管理制度
  • 无锡朝阳网站推广荔枝视频在线观看免费最新
  • 网站首页title简单描述网络营销的特点
  • photoshop 网站设计运营培训班有用吗
  • dede企业网站模板下载电脑打不开网页怎么回事
  • 即时设计是什么软件seo项目完整流程
  • 建设工程合同备案网站wordpress右侧空白
  • wordpress 顶部图像汉阳网站推广优化
  • html公益网站模板大型百度云网站建设
  • 网站移动端开发公司培训行业门户网站建设方案
  • 百度经验app下载seo移动端排名优化
  • 黄岛网站建设哪家专业title 芜湖网站制作
  • 济宁华园建设有限公司网站怎么做网站促收录
  • 广州市建设企业网站哪家好网络规划设计 网站建设
  • 徐州营销型网站建设c 网站开发 readonly属性