线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程的出现是为了更加合理的利用CPU资源 创建线程有2种方法,一种是继承Thread类,另一种就是实现Runable 新建一个类继承Thread类并重写run()方法: 新建一个类实现Runnable接口并重写run()方法: 上面是线程的两种基本形式,我们有时候创建线程也可以用下面的简写形式进行直接创建: 线程中总共有六种状态。 NEW表示线程尚未启动的状态,即当我们new 一个线程时,线程就是NEW状态。 上面输出的状态就是:NEW 可运行状态或者说就绪状态。当我们调用thread.start()之后,线程就进入RUNNABLE状态,注意,调用start()方法之后线程并不一定会马上执行,还要看操作系统的调度才能执行。 上面的第二个输出语句中线程t1的状态就是RUNNABLE状态 t1线程启动之后,我们把主线程休眠1s,t1执行完毕之后再看t1的状态就是TERMINATED 等待状态,当调用wait(),join()或者park()方法时,线程就会处于WAITING等待状态 运行之后通过jps和jstack命令可以看到t2线程就是TIMED_WAITING状态,而t1就是WAITING状态 和上面WAITING状态一样,只是有一个等待时间,一般调用如下方法时:sleep(),wait(),join(),LockSupport.parkNanos(),LockSupport.parkUntil(),而且方法带上时间则线程会出现这个状态。 线程等待锁时被阻塞状态。一个线程正在等待进入一个同步代码块时线程会被阻塞或者被调用之后重入一个同步代码块时被阻塞。 上面示例中t3和t4争抢同一把锁进入同步代码块,那么一定会有一个线程处于BLOCKED状态: 经过上面的分析,我们可以得到一张线程的生命周期简图: 线程当中有三个关于中断的方法: 这里的输出结果为false,这是因为判断条件里面调用了一次为true,然后对线程进行了复位,所以run()方法内输出了false。 实际上: isInterrupted()和 interrupted()方法最终都调用的是下面这个本地方法,只不过isInterrupted()方法默认传了false(不复位),而 interrupted()默认传了true(复位) 这是因为我们并不建议直接去中断一个线程,假如一个线程正在执行一系列操作,那么强行中断,可能会引起其他问题(这也是stop()方法之所以标记为过期的原因),所以中断只是打一个标记,然后由线程自己去获取中断标记,再决定要不要中断。 就比如我们上面的while循环中,我们获取到中断标记,然后内部可以决定是继续执行循环体还是直接返回终止线程。 为什么需要对线程复位? 我们都知道,每次调用sleep()的时候都需要抛出一个InterruptedException异常 这里输出结果为false,这就说明当我们一个休眠的线程被中断后,抛出异常的同时也会对线程的中断标记进行复位,这一点是需要注意的。 我们还是先来看下面的一个例子: 输出结果如下图: 首先我们看第一行代码: 因为MyThread继承了Thread,所以会调用默认的无参构造器: 然后第二行代码我们再把这个线程传进去重新new一个线程又会发生什么?这时候调用的是另一个有参构造器: 实际上这产生了一个现象,最后的结果是t1线程中的target线程才是我们的myThread线程,也就是最后执行run()方法的是target中的对象(myThread)去执行。所以this获取到的名字是target中线程的名字,而currentThread()获取到的是当前线程t1的名字。 那如果我们不创建t1线程,直接调用myThread.start()呢,这时候的结果两个都会输出Thread-0,因为这时候this对象就是myThread,当前线程是myThread。Thread状态及interrupted作用分析
什么是线程
如何创建线程
继承Thread类
package com.zwx.thread; public class MyThread extends Thread { @Override public void run() { System.out.println("111"); } }
package com.zwx.thread; public class CreateThreadDemo{ public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
实现Runnable接口
package com.zwx.thread; public class MyThread1 implements Runnable { @Override public void run() { System.out.println("111"); } }
package com.zwx.thread; public class CreateThreadDemo{ public static void main(String[] args) { MyThread1 myThread1 = new MyThread1(); Thread thread = new Thread(myThread1); thread.start(); } }
创建线程简写形式
package com.zwx.thread; public class CreateThreadDemo{ public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("我是t1"); } },"t1"); t1.start(); new Thread(()->{ System.out.println("我是t2"); },"t2").start(); } }
线程的生命周期
NEW
package com.zwx.thread; public class ThreadState { public static void main(String[] args) { Thread t1 = new Thread(()->{ System.out.println("我是t1线程"); }); System.out.println(t1.getState()); } }
RUNNABLE
package com.zwx.thread; public class ThreadState { public static void main(String[] args) { Thread t1 = new Thread(()->{ System.out.println("我是t1线程"); }); System.out.println(t1.getState());//NEW t1.start(); System.out.println(t1.getState());//RUNNABLE } }
TERMINATED
package com.zwx.thread; public class ThreadState { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ System.out.println("我是t1线程"); }); System.out.println(t1.getState());//NEW t1.start(); Thread.sleep(1000); System.out.println(t1.getState());//TERMINATED } }
WAITING
package com.zwx.thread; public class ThreadState { public static void main(String[] args) throws InterruptedException { new Thread(()->{ while (true){ synchronized (ThreadState.class){ System.out.println("我是t1线程"); try { ThreadState.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } },"t1").start(); new Thread(()->{ while (true){ System.out.println("我是t2线程"); try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } } },"t2").start(); } }
TIMED_WAITING
示例同上面的WAITING中的示例BLOCKED
package com.zwx.thread; public class ThreadState { static class BlockDemo extends Thread{ @Override public void run() { synchronized (BlockDemo.class){ while (true){ } } } } public static void main(String[] args) { new Thread(new BlockDemo(),"t3").start(); new Thread(new BlockDemo(),"t4").start(); } }
线程生命周期图
interrupted()作用
我们来看下面一个例子:package com.zwx.thread.baseapi; public class ThreadInterruptDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ int i=0; while(Thread.interrupted()){ System.out.println("我是线程" + Thread.currentThread().getName() + ":" + Thread.interrupted());//false } },"t1"); t1.start(); t1.interrupt(); } }
线程中断标记有什么用呢?
我们设想这么一种场景,假如我们规定收到3次线程中断要求的时候,即使线程没有执行完毕这时候也需要直接返回,那么线程如果不复位,我们就没办法知道当前线程进行过多少次中断(不考虑同时多次中断的情况),因为中断过一次,一直是true;而有了线程复位,我们就只需要判断3次都是true就说明至少被中断过3次。当interrupt()遇到sleep()
老规矩,还是来看一个例子:package com.zwx.thread.baseapi; public class InterruptSleepThreadDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ try { Thread.sleep(10000); } catch (InterruptedException e) { System.out.println(Thread.currentThread().isInterrupted());//false } },"t1"); t1.start(); Thread.sleep(1000); t1.interrupt(); } }
currentThread()和this的区别
package com.zwx.thread.baseapi; public class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName());//t1 System.out.println(this.getName());//Thread-0 } }
package com.zwx.thread.baseapi; public class CurrentThreadAndThis { public static void main(String[] args) { MyThread myThread = new MyThread(); Thread t1 = new Thread(myThread,"t1"); t1.start(); } }
为什么this.getName()不会输出t1,很多人的理解中这两种应该是等价的。其实不然,this指的是当前对象,也就是MyThread对象,而currentThread()才是指的当前线程t1。MyThread myThread = new MyThread();
这时候会产生一个name为:Thread-0的线程。
我们发现,myThread作为target被传入进去,断点后发现我们最开始创建的线程Thread-0被赋在t1对象的traget中:
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算