主页 > 创业  > 

第1章快速认识线程

第1章快速认识线程

1.1 线程的介绍

对于计算机来说每一个任务就是一个进程Process,在每一个进程内部至少要有一个线程Thread是在运行中的。

1.2 快速创建并启动一个线程
1.2.1 尝试并行运行
package chapter01; import java.util.concurrent.TimeUnit; public class TryConcurrency { private static void browsNews() { while (true) { System.out.println("good news"); sleep(1); } } private static void enjoyMusic() { while (true) { System.out.println("good music"); sleep(1); } } private static void sleep(double seconds) { try { Thread.sleep((long) (seconds * 1000)); } catch (InterruptedException e) { throw new RuntimeException(e); } } public static void main(String[] args) { browsNews(); enjoyMusic(); } } 输出 : good news good news good news ... good news good news good news 1.2.2 并发运行交替输出

更改一下main方法

new Thread(TryConcurrency::browsNews).start(); enjoyMusic(); 或 new Thread(new Runnable() { @Override public void run() { browsNews(); } }).start(); enjoyMusic(); 1.2.3 使用Jconsole观察线程
1.3 线程的生命周期详解

每个线程都有自己的局部变量表,程序计数器,以及生命周期等。

线程的生命周期大体可以分为5个阶段 :

NEWRUNNABLERUNNINGBLOCKEDTERMINATED 1.3.1 线程的NEW状态

当你创建了一个Thread对象,但没有调用start方法时线程处于NEW状态。 NEW状态通过start方法进入RUNNABLE状态。

1.3.2 线程的RUNNABLE状态

线程一旦调用start会立即进入RUNNABLE状态,但并不会立即执行,线程的运行与否要听命于CPU的调度。

1.3.3 线程的RUNNING状态

一旦CPU通过轮询或者其他方式从任务可执行队列中选中了线程,那么此时它才能真正地执行自己的逻辑代码,需要说明的一点是一个正在RUNNING状态的线程事实上也是RUNNABLE的,但是反过来则不成立。

1.3.4 线程的BLOCKED状态
1.3.5 线程的TERMINATED状态

TERMINATED是一个线程的最终状态,意味着整个线程的生命周期都结束了。

1.4 线程的start方法剖析:模板设计模式在Thread中的应用

当启动一个线程时调用的是start方法,而被重写的方法是run方法,二者之间有怎样不为人知的关系呢。

1.4.1 Thread start方法源码分析以及注意事项

这是Thread start方法的源码

public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } }

start方法内部会调用private native void start0();这个本地方法

Thread被构造后的NEW状态,由threadStatus这个内部属性设置为0来表示不能启动两次Thread,否则抛出IllegalThreadStateException异常当线程启动后会被加入到ThreadGroup中。当线程的生命周期结束后,也就是TERMINATED状态,再次调用start方法也是不被允许的

连续两次启动同一线程

package chapter01; import java.util.concurrent.TimeUnit; public class Test04 { public static void main(String[] args) { // 匿名内部类 Thread thread = new Thread() { @Override public void run() { try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } } }; thread.start(); // 两次启动同一线程会抛出异常 thread.start(); } } 输出 : Exception in thread "main" java.lang.IllegalThreadStateException at java.base/java.lang.Thread.start(Thread.java:802) at chapter01.Test04.main(Test04.java:19)

在线程结束后再次启动线程

package chapter01; import java.util.concurrent.TimeUnit; public class Test04 { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread() { @Override public void run() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { throw new RuntimeException(e); } } }; thread.start(); // 确保线程已经结束 TimeUnit.SECONDS.sleep(2); thread.start(); } } 输出 : Exception in thread "main" java.lang.IllegalThreadStateException at java.base/java.lang.Thread.start(Thread.java:802) at chapter01.Test04.main(Test04.java:20)

也会抛出IllegalThreadStateException异常。

1.4.2 模板设计模式在Thread中的应用

线程的真正执行逻辑是在run方法中的,通常把run方法称为线程的执行单元。

其实Thread的start和run是一个典型的模板设计模式,父类编写算法结构代码,子类实现逻辑细节。

下面是一个简易的模板设计模式的代码

package chapter01; public class TemplateMethod { public final void print(String msg) { System.out.println("--------------------"); wrapPrint(msg); System.out.println("--------------------"); } public void wrapPrint(String msg) { } public static void main(String[] args) { new TemplateMethod() { @Override public void wrapPrint(String msg) { System.out.println("Hello " + msg + "Hello"); } }.print("你好"); System.out.println(); new TemplateMethod() { @Override public void wrapPrint(String msg) { System.out.println("nihk " + msg + "nihk"); } }.print("你好"); } } 输出 : -------------------- Hello 你好Hello -------------------- -------------------- nihk 你好nihk -------------------- 1.4.3 Thread 模拟营业大厅叫号机程序

启动四个线程售票

package chapter01; import java.util.concurrent.TimeUnit; public class TicketWindows extends Thread { private final String name; private static final int MAX = 50; private static int index = 1; public TicketWindows(String name) { this.name = name; } @Override public void run() { while (index <= MAX) { System.out.println("柜台 : " + name + "当前的号码 : " + (index++)); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public static void main(String[] args) { // 开启四个窗口 new TicketWindows("anan").start(); new TicketWindows("jcjc").start(); new TicketWindows("yjyj").start(); new TicketWindows("yryr").start(); } } 1.5 Runnable接口的引入以及策略模式在Thread中的使用
1.5.1 Runnable的职责

Runnable接口非常简单,只定义了一个无参数无返回值的run方法。

public interface Runnable { public abstract void run(); }

创建线程只有一种方式就是构造Thread类,而实现线程的执行单元则有两种方式,第一种是重写Thread的run方法,第二种是实现Runnable接口的run方法,并将Runnable实例用作构造Thread的参数。

1.5.2 策略模式在Thread中的应用
1.5.3 模拟营业大厅叫号机程序

其实就是用Runnable接口重写了一下之前直接继承Thread的写法。

1.6 本章总结
标签:

第1章快速认识线程由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“第1章快速认识线程