前言
引用 百度 百科对 线程 的解释
多线程 (multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括 对称多处理机 、多核心处理器以及芯片级多处理或同时多线程处理器。在一个 程序 中,这些独立运行的程序片段叫作“ 线程 ”(Thread),利用它编程的概念就叫作“多线程处理”。总而言之。多线程是为了解决处理事情的性能和效能的一种手段。然而进程和线程是存在一种关系。简单的例子,你使用一个软件,然后你在系统后台看到的一个个服务就是一个个进程,而进程里面可以有多个线程来处理一些事件。
生命周期
在 JAVA虚拟机 中对线程定义了6个状态,可以 java .lang.Thread. state 枚举类型中找到。
NEW: 线程已经创建,但是还没有start,这就是我们new Thread的时候最后需要调用start方法
RUNNABLE: 在 Java 虚拟机 中执行的线程。
B lock ED: 阻塞等待监视器锁的线程处于此状态。
WAITING: 无限期等待另一个线程执行特定操作的线程
TIMED_WAITING:具有指定等待时间的等待线程的线程状态。
TERMINATED: 终止状态,也就是这个线程已经执行完了
状态转变demo
1、new->Runnable->terminated
public static void main(String[] args) throws Interrupted Exception {
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
}
}
},"Thread-2");
while (true) {
System.out.println(thread2.getName()+",state:"+thread2.getState());
if (thread2.getState() == Thread.State.NEW) {
thread2.start();
}
if (thread2.getState() == Thread.State.TERMINATED ) {
System.out.println(thread2.getName()+",state:"+thread2.getState());
break;
}
}
}
2、new->Runnable->waiting->terminated
private static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
//先休眠1秒,让主线程先执行打印
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//上锁,也就是上监控,这个后面再细讲
synchronized (lock) {
try {
//这里执行了await方法,需要结合synchronized关键字
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Thread-2");
int i = 0;
while (true) {
System.out.println(thread2.getName()+",state:"+thread2.getState());
if (thread2.getState() == Thread.State.NEW) {
thread2.start();
}
if (thread2.getState() == Thread.State.TERMINATED ) {
System.out.println(thread2.getName()+",state:"+thread2.getState());
break;
}
//执行notify唤醒线程
if (i == 5) {
synchronized (lock) {
lock.notify();
}
}
TimeUnit.SECONDS.sleep(1);
i++;
}
}
3、BLOCK状态
static class Counter {
int counter;
//同步
public synchronized void increase() {
counter++;
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws InterruptedException {
Counter c = new Counter();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
c.increase();
}
},"Thread-2");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
c.increase();
}
}," Thread- 1");
thread2.start();
thread1.start();
while (true) {
System.out.println(thread2.getName()+",state:"+thread2.getState());
System.out.println(thread1.getName()+",state:"+ Thread 1.getState());
if (thread1.getState() == Thread.State.TERMINATED && thread2.getState() == Thread.State.TERMINATED ) {
break;
}
TimeUnit.SECONDS.sleep(1);
}
}
这个效果和 jdk 文档的BLOCK状态的描述一样。翻译:线程阻塞等待监视器锁的线程状态。处于阻塞状态的线程正在等待监视器锁进入同步块的方法或调用 Object.wait 后重新进入同步块方法。也是需要等待锁进入或者锁重入。
其他方法就很容易打印出来了,time_waiting,sleep方法就可以打印出time_waiting
Thread类中的其他方法
1、 yield :官方解释;向调度程序提示当前线程愿意放弃其当前对处理器的使用。
调度程序可以随意忽略此提示。
Yield 是一种启发式尝试,旨在改善线程之间的相对进展,否则会过度使用 CPU 。
它的使用应与详细的分析和基准测试相结合,以确保它实际上具有预期的效果。
说的通俗易懂的就是,会让出自己的占用的资源暂时给其他线程或者自己使用;这个就得看系统调度了。
demo
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
if (i == 2) {
Thread.currentThread().yield();
}
}
}
},"Thread-1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
if (i == 4) {
Thread.currentThread().yield();
}
}
}
},"Thread-2");
thread1.start();
thread2.start();
}
执行结果可能不太一样。这个就有点明显,当线程1中的i=2时,就会让出资源给线程2拿到,当线程2中的i=4时,也会让出资源给线程1。
2、join
join方法就有点一下,就是当前线程加入其他线程,需要当前线程执行完后,其他线程才能执行。这个就有点霸道的感觉。
demo
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始执行。。。");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行结束。。。");
}
},"Thread-1");
thread1.start();
thread1.join();
System.out.println("主线程开始执行");
}
如果没有thread1.join()这句的话,你会发现,执行结果不大一样;
3、interrupt
指的是线程中断。但是具体的案例,本人没有弄出来,因为达不到想要的效果。后面找找资料再研究研究。再和你们分享。
总结
本篇主要是讲解一下 JVM 中线程的生命周期,和java提供的Thread的简单使用,后面会加入 线程安全 的知识再分享一些小案例。
一天一个java相关小知识。喜欢的同学,可以点赞、关注+收藏,后期还会推出其他框架源码分析。
如果有需要补充的地方,留言区见。