线程与过程
概念
过程:过程指的是一段正在运行的程序
线程:一个程序运行中能够执行多个工作,工作就称之为线程。
过程能够有多个线程,各个线程之间共享程序的内存空间
为什么有了过程,还会呈现线程?
每个过程有本人独立的地址空间,多并发申请,为每一个申请创立一个过程,导致系统开销、用户申请效率低
区别
每个过程有用本人独有的变量,线程共享数据,线程之间的通信相比于过程之间的通信更加无效,更加容易
线程相比于过程创立 / 销毁开销 更小
过程是资源分配的最小单位,线程是 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、分布式缓存、数据结构等等。