线程与过程
概念
过程:过程指的是一段正在运行的程序
线程:一个程序运行中能够执行多个工作,工作就称之为线程。
过程能够有多个线程,各个线程之间共享程序的内存空间
为什么有了过程,还会呈现线程?
每个过程有本人独立的地址空间,多并发申请,为每一个申请创立一个过程,导致系统开销、用户申请效率低
区别
每个过程有用本人独有的变量,线程共享数据,线程之间的通信相比于过程之间的通信更加无效,更加容易
线程相比于过程创立/销毁开销 更小
过程是资源分配的最小单位,线程是CPU调度的最小单位
多过程程序更加强壮,多线程程序只有有一个线程挂掉,对其共享资源的其余线程也回产生影响
如果谋求速度,谋求零碎稳固抉择线程;如果频繁的创立和销毁,抉择线程;
线程的创立
说完线程的基本知识,那么久要谈谈在利用中,咱们应该如何创立线程,理论利用中创立线程次要有以下四种办法,如下:
办法一:继承Thread类,重写run()办法
class MyThread extends Thread{ @Override public void run() { while(true){ System.out.println("eat food"); } }}public class TestDemo1 { public static void main(String[] args) { //边吃饭边看电视 //创立子线程对象 Thread thread = new MyThread(); //启动吃饭的thread thread.run(); //main线程 while(true){ System.out.println("watch Tv"); } } }
办法二:实现Runable接口
class MyRunnable implements Runnable{ @Override public void run() { while(true){ System.out.println("eat food"); } }}public class TestDemo1 { public static void main(String[] args) { //实现runnable接口 创立子线程 创立子线程对象 Thread thread = new Thread(new MyRunnable()); thread.start(); } }
办法三:匿名线程 应用匿名外部类
//匿名外部类 创立线程 new Thread(){ @Override public void run() { System.out.println("thread 0"); } }.start();
办法四:实现Callable接口,重写call()办法
利用Callable创立时,步骤较为简单,具体如下:
a.创立Callable接口的实现类,重写call办法
b.创立Callable实现类的实例,应用FutureTask包装该实例
c.将FutureTask实例作为参数创立线程对象
d.启动该线程
e.调用FutureTask的get办法获取子线程的执行后果
class MyCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { int sum = 0; for(int i=0; i<10000; i++){ sum += i; } return sum; }}public class TestDemo1 { public static void main(String[] args) { //创立Callable接口的实现类 重写call 办法 //创立Callable实现类的实例 Callable<Integer> callableTask = new MyCallable(); //应用FutureTask包装实例 FutureTask<Integer> task = new FutureTask<>(callableTask); //Future实例作为参数创立线程对象 Thread thread = new Thread(task); //启动该线程 thread.start(); //调用FutureTask的get 办法获取子线程的执行后果 try { Integer integer = task.get(); System.out.println("result"+integer); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }
可能有人会思考,这里同样应用Runable和Callable接口来创立线程,那么这两者各有什么不同呢?能想到这,堪称是很用心啦,这也是这里的一个面试考点呐!!!
Runable 接口和 Callable 接口的区别?
这里就简略说一下两者的区别,然而仅仅独自比拟两个接口的区别实际意义并不大,并且也不是很全面,之后会
具体的剖析两个接口的区别,在更深层次下来了解两个接口。大家持续关注吖!
线程的生命周期及罕用办法解析
生命周期
线程的生命周期次要包含以下六种状态:新建状态、就绪状态、阻塞状态、期待状态、睡眠状态、终止状态。
1、new() :新建状态 new关键字创立一个线程对象,它并不是出于执行状态 并未执行START办法启动线程 2、runnable() :就绪状态 期待被执行 线程对象调用START办法,才是JVM中真正创立了一个线程, 创立好的线程并不是一经启动,就会立刻执行。该状态的所有线程会位于就绪线程池中,期待以后操作系统的资源,例如CPU, 取得CPU的使用权。 3、blocked(): 阻塞状态 期待一个监视器锁进入同步代码块或者同步办法,代码块和办法指某一时刻 只可能有一个线程去执行,其余线程只能期待。 4、Waiting(): 期待状态 Object.wait()/Thread.join()/LockSupport.park() 都会使得以后从Runnable 转换为Waiting 状态 调用waiting() 会开释monitor Lock 5、TimeWaiting():睡眠状态 调用Object.wait(long miles)/Thread.sleep(long miles)/LockSupport.parkNano()/LockSupport.parkUntile() 6、Terminated():终止状态 是一个线程的最终状态 线程如果进入此状态,意味着该线程完结。
简略理解线程的生命周期之后,那咱们持续学习线程六状态之间的转换:
罕用办法解析
1) start()
启动一个线程,将线程增加到线程组中,线程状态会从New 状态转换到Runnable 状态,而后获取CPU之后进入Running状态执行run();
2)sleep()
静态方法 ,存在两个重载函数
public static native void sleep(long millis) public static void sleep(long millis, int nanos)
作用:sleep()办法使得以后线程进入睡眠状态并指定休眠工夫,暂停执行;
sleep()办法不会开释Monitor Lock 使用权;
JDK1.5之后,引入枚举类TimeUnit ,其对sleep进行封装 间接应用从而省去工夫换算的步骤,不必将工夫转为ms,更加的方便使用。
3)yield()
public static native void yield();
作用: 揭示CPU调度器 ,我以后的线程违心放弃以后的CPU资源(属于启发式办法),如果以后CPU资源不缓和,会疏忽这种揭示。
yield()办法不会开释Monitor Lock 使用权;
4)join()
join() 始终期待join(long millis) 期待指定毫秒数join(long millis, int nanos) 期待指定毫秒数
含意:在线程B中join某个线程A,会使得B线程进入期待,直到线程A完结生命周期,或者达到给定的工夫,在这给定工夫期间线程B会处于期待状态.
5)wait()
调用某个对象的wait()办法能够让以后线程阻塞
6)notify()
调用以后对象notify/notifyAll才可能唤醒这个对象所在的线程。
7)notifyAll()
将锁对象期待池中所有线程挪动到锁标记期待池中。
留神:应用这三个办法须要让以后线程领有以后对象的monitor lock
8)线程中断办法
每个Java线程都会有一个中断状态位,程序能够检测这个中断状态位判读线程是否执行完结。有以下三种办法:
interrupt()
public void interrupt() 由线程对象调用,将中断地位置为true
public void interrupt();
如下办法可能使得以后线程进入阻塞状态,调用interrupt办法能够打断阻塞,因而这种办法被称之为可中断办法
Object.wait()/wait(long)Thread.sleep(long)/TimUnit.XXX.sleep(long)Thread.join()/Thread.join(long)
如果一个线程被interrupt,设置interrupt flag;如果以后线程正在执行可中断办法,调用interrupt办法,反而导致interrupt flag被革除.
isInterrupted
public boolean isInterrupted();
实例办法,判断以后线程的中断状态位是否为true,判断过程是否被中断。
interrupted()
public static boolean interrupted();
静态方法,调用interrupted会擦除中断状态位的标识,判断过程是否被中断
interrupted和isInterrupted办法的区别:
1)interrupted()是静态方法,isInterrupted()是实例办法;
2)interrupted()会清空线程中断状态,isInterrupted()不会清空线程中断状态。
最初
欢送关注公众号:前程有光,支付一线大厂Java面试题总结+各知识点学习思维导+一份300页pdf文档的Java外围知识点总结! 这些材料的内容都是面试时面试官必问的知识点,篇章包含了很多知识点,其中包含了有基础知识、Java汇合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。